~brandontschaefer/unity/bump-to-new-nux-abi

« back to all changes in this revision

Viewing changes to unity-shared/TextInput.cpp

  • Committer: CI bot
  • Author(s): Marco Trevisan (Treviño)
  • Date: 2014-09-04 22:11:03 UTC
  • mfrom: (3844.10.37 scaling-lockscreen)
  • Revision ID: ps-jenkins@lists.canonical.com-20140904221103-y9g3g7yrsbi7zsbr
Lockscreen: scale the UI elements based on current monitor scaling Fixes: 1292218
Approved by: PS Jenkins bot, Andrea Azzarone

Show diffs side-by-side

added added

removed removed

Lines of Context:
17
17
 * Authored by: Manuel de la Pena <manuel.delapena@canonical.com>
18
18
 */
19
19
 
 
20
#include "config.h"
20
21
#include "TextInput.h"
21
 
#include "unity-shared/IconTexture.h"
22
 
#include "unity-shared/DashStyle.h"
23
 
#include "unity-shared/RawPixel.h"
24
 
#include "unity-shared/PreviewStyle.h"
25
 
#include "unity-shared/TextureCache.h"
 
22
 
 
23
#include <gtk/gtk.h>
 
24
#include <glib/gi18n-lib.h>
 
25
 
 
26
#include <Nux/LayeredLayout.h>
 
27
#include <Nux/HLayout.h>
 
28
#include <Nux/VLayout.h>
 
29
#include <NuxCore/Logger.h>
 
30
 
 
31
#include "CairoTexture.h"
 
32
#include "StaticCairoText.h"
 
33
#include "IconTexture.h"
 
34
#include "IMTextEntry.h"
 
35
#include "DashStyle.h"
 
36
#include "PreviewStyle.h"
 
37
#include "RawPixel.h"
 
38
#include "TextureCache.h"
 
39
#include "UnitySettings.h"
26
40
 
27
41
namespace unity
28
42
{
29
43
 
30
44
namespace
31
45
{
32
 
const float kExpandDefaultIconOpacity = 1.0f;
33
 
 
34
 
const int SPACE_BETWEEN_ENTRY_AND_HIGHLIGHT = 10;
35
 
const int LEFT_INTERNAL_PADDING = 6;
36
 
const int TEXT_INPUT_RIGHT_BORDER = 10;
37
 
 
38
 
const int HIGHLIGHT_HEIGHT = 24;
 
46
const int BORDER_RADIUS = 5;
 
47
const int TOOLTIP_WAIT = 500;
 
48
const RawPixel SPACE_BETWEEN_ENTRY_AND_HIGHLIGHT = 10_em;
 
49
const RawPixel LEFT_INTERNAL_PADDING = 6_em;
 
50
const RawPixel TEXT_INPUT_RIGHT_BORDER = 10_em;
 
51
const RawPixel HINT_PADDING = 3_em;
39
52
 
40
53
const RawPixel TOOLTIP_Y_OFFSET  =  3_em;
41
54
const RawPixel TOOLTIP_OFFSET    = 10_em;
47
60
const int HINT_LABEL_FONT_SIZE = 11;
48
61
 
49
62
const std::string PANGO_ENTRY_DEFAULT_FONT_FAMILY = "Ubuntu";
50
 
const int PANGO_ENTRY_FONT_SIZE = 14;
51
 
 
52
 
}
 
63
const RawPixel PANGO_ENTRY_FONT_SIZE = 14_em;
53
64
 
54
65
nux::logging::Logger logger("unity.textinput");
55
66
 
56
 
NUX_IMPLEMENT_OBJECT_TYPE(TextInput);
57
 
 
58
 
nux::AbstractPaintLayer* CreateWarningLayer(nux::BaseTexture* texture)
 
67
std::shared_ptr<nux::AbstractPaintLayer> CreateWarningLayer(nux::BaseTexture* texture)
59
68
{
60
69
  // Create the texture layer
61
70
  nux::TexCoordXForm texxform;
71
80
  rop.SrcBlend = GL_ONE;
72
81
  rop.DstBlend = GL_ONE_MINUS_SRC_ALPHA;
73
82
 
74
 
  return (new nux::TextureLayer(texture->GetDeviceTexture(),
75
 
                                texxform,
76
 
                                nux::color::White,
77
 
                                true,
78
 
                                rop));
79
 
}
 
83
  return std::make_shared<nux::TextureLayer>(texture->GetDeviceTexture(), texxform, nux::color::White, true, rop);
 
84
}
 
85
}
 
86
 
 
87
NUX_IMPLEMENT_OBJECT_TYPE(TextInput);
80
88
 
81
89
TextInput::TextInput(NUX_FILE_LINE_DECL)
82
90
  : View(NUX_FILE_LINE_PARAM)
85
93
  , hint_font_size(HINT_LABEL_FONT_SIZE)
86
94
  , show_activator(false)
87
95
  , show_caps_lock(false)
 
96
  , scale(1.0)
88
97
  , bg_layer_(new nux::ColorLayer(nux::Color(0xff595853), true))
89
98
  , caps_lock_on(false)
90
99
  , last_width_(-1)
91
100
  , last_height_(-1)
92
 
  , mouse_over_warning_icon_(false)
93
101
{
94
102
  layout_ = new nux::HLayout(NUX_TRACKER_LOCATION);
95
 
  layout_->SetLeftAndRightPadding(LEFT_INTERNAL_PADDING, TEXT_INPUT_RIGHT_BORDER);
96
 
  layout_->SetSpaceBetweenChildren(SPACE_BETWEEN_ENTRY_AND_HIGHLIGHT);
 
103
  layout_->SetLeftAndRightPadding(LEFT_INTERNAL_PADDING.CP(scale), TEXT_INPUT_RIGHT_BORDER.CP(scale));
 
104
  layout_->SetSpaceBetweenChildren(SPACE_BETWEEN_ENTRY_AND_HIGHLIGHT.CP(scale));
97
105
  SetLayout(layout_);
98
106
 
99
 
  nux::HLayout* hint_layout = new nux::HLayout(NUX_TRACKER_LOCATION);
100
 
  hint_layout->SetLeftAndRightPadding(3, 3);
 
107
  hint_layout_ = new nux::HLayout(NUX_TRACKER_LOCATION);
 
108
  hint_layout_->SetLeftAndRightPadding(HINT_PADDING.CP(scale), HINT_PADDING.CP(scale));
101
109
 
102
110
  hint_ = new StaticCairoText("");
103
111
  hint_->SetTextColor(nux::Color(1.0f, 1.0f, 1.0f, 0.5f));
104
 
  hint_layout->AddView(hint_, 0, nux::MINOR_POSITION_CENTER, nux::MINOR_SIZE_FULL);
 
112
  hint_->SetScale(scale);
 
113
  hint_layout_->AddView(hint_, 0, nux::MINOR_POSITION_CENTER, nux::MINOR_SIZE_FULL);
105
114
  hint_font_name.changed.connect(sigc::hide(sigc::mem_fun(this, &TextInput::UpdateHintFont)));
106
115
  hint_font_size.changed.connect(sigc::hide(sigc::mem_fun(this, &TextInput::UpdateHintFont)));
107
116
  UpdateHintFont();
108
117
 
109
118
  pango_entry_ = new IMTextEntry();
110
119
  pango_entry_->SetFontFamily(PANGO_ENTRY_DEFAULT_FONT_FAMILY.c_str());
111
 
  pango_entry_->SetFontSize(PANGO_ENTRY_FONT_SIZE);
112
120
  pango_entry_->cursor_moved.connect([this](int i) { QueueDraw(); });
113
121
  pango_entry_->mouse_down.connect(sigc::mem_fun(this, &TextInput::OnMouseButtonDown));
114
122
  pango_entry_->end_key_focus.connect(sigc::mem_fun(this, &TextInput::OnEndKeyFocus));
117
125
  });
118
126
 
119
127
  layered_layout_ = new nux::LayeredLayout();
120
 
  layered_layout_->AddLayer(hint_layout);
 
128
  layered_layout_->AddLayer(hint_layout_);
121
129
  layered_layout_->AddLayer(pango_entry_);
122
130
  layered_layout_->SetPaintAll(true);
123
131
  layered_layout_->SetActiveLayerN(1);
124
132
  layout_->AddView(layered_layout_, 1, nux::MINOR_POSITION_CENTER, nux::MINOR_SIZE_FIX);
125
133
 
 
134
  UpdateSize();
 
135
 
126
136
  // Caps lock warning
127
 
  warning_ = new IconTexture(LoadWarningIcon(DEFAULT_ICON_SIZE));
 
137
  warning_ = new IconTexture(LoadWarningIcon(DEFAULT_ICON_SIZE.CP(scale)));
128
138
  warning_->SetVisible(caps_lock_on());
129
139
  layout_->AddView(warning_, 0, nux::MINOR_POSITION_CENTER, nux::MINOR_SIZE_FULL);
130
140
  caps_lock_on.changed.connect([this] (bool on) {
136
146
    }
137
147
  });
138
148
 
139
 
  show_caps_lock.changed.connect([this] (bool changed) {
140
 
    if (!warning_tooltip_.IsValid())
141
 
      LoadWarningTooltip();
142
 
 
143
 
    CheckIfCapsLockOn();
144
 
  });
 
149
  show_caps_lock.changed.connect(sigc::hide(sigc::mem_fun(this, &TextInput::CheckIfCapsLockOn)));
 
150
  scale.changed.connect(sigc::mem_fun(this, &TextInput::UpdateScale));
 
151
  Settings::Instance().font_scaling.changed.connect(sigc::hide(sigc::mem_fun(this, &TextInput::UpdateSize)));
145
152
 
146
153
  // Activator
147
 
  activator_ = new IconTexture(LoadActivatorIcon(DEFAULT_ICON_SIZE));
 
154
  activator_ = new IconTexture(LoadActivatorIcon(DEFAULT_ICON_SIZE.CP(scale)));
148
155
  activator_->SetVisible(show_activator());
149
156
  layout_->AddView(activator_, 0, nux::MINOR_POSITION_CENTER, nux::MINOR_SIZE_FULL);
150
157
 
159
166
  // Spinner
160
167
  spinner_ = new SearchBarSpinner();
161
168
  spinner_->SetVisible(false);
162
 
  spinner_->SetMinMaxSize(22, 22);
 
169
  spinner_->scale = scale();
163
170
  layout_->AddView(spinner_, 0, nux::MINOR_POSITION_CENTER, nux::MINOR_SIZE_FULL);
164
171
 
165
 
  sig_manager_.Add<void, GtkSettings*, GParamSpec*>(gtk_settings_get_default(),
166
 
    "notify::gtk-font-name", sigc::mem_fun(this, &TextInput::OnFontChanged));
167
 
  OnFontChanged(gtk_settings_get_default());
 
172
  sig_manager_.Add<void, GtkSettings*>(gtk_settings_get_default(), "notify::gtk-font-name", sigc::hide(sigc::mem_fun(this, &TextInput::OnFontChanged)));
 
173
  OnFontChanged();
 
174
 
 
175
  sig_manager_.Add<void, GdkKeymap*>(gdk_keymap_get_default(), "state-changed", [this](GdkKeymap*) {
 
176
    CheckIfCapsLockOn();
 
177
  });
168
178
 
169
179
  sig_manager_.Add<void, GdkKeymap*>(gdk_keymap_get_default(), "state-changed", [this](GdkKeymap*) {
170
180
    CheckIfCapsLockOn();
177
187
  input_hint.changed.connect([this](std::string const& s) { OnInputHintChanged(); });
178
188
 
179
189
  warning_->mouse_enter.connect([this] (int x, int y, int button, int key_flags) {
180
 
    mouse_over_warning_icon_ = true;
181
 
    QueueDraw();
 
190
    tooltip_timeout_.reset(new glib::Timeout(TOOLTIP_WAIT, [this] {
 
191
      tooltip_timeout_.reset();
 
192
      QueueDraw();
 
193
      return false;
 
194
    }));
182
195
  });
183
196
 
184
197
  warning_->mouse_leave.connect([this] (int x, int y, int button, int key_flags) {
185
 
    mouse_over_warning_icon_ = false;
186
 
    QueueDraw();
 
198
    tooltip_timeout_ ? tooltip_timeout_.reset() : QueueDraw();
187
199
  });
188
200
}
189
201
 
 
202
void TextInput::UpdateSize()
 
203
{
 
204
  pango_entry_->SetFontSize(PANGO_ENTRY_FONT_SIZE.CP(scale * Settings::Instance().font_scaling()));
 
205
  int entry_min = pango_entry_->GetMinimumHeight();
 
206
  pango_entry_->SetMaximumHeight(entry_min);
 
207
  layered_layout_->SetMinimumHeight(entry_min);
 
208
  layered_layout_->SetMaximumHeight(entry_min);
 
209
}
 
210
 
 
211
void TextInput::UpdateScale(double scale)
 
212
{
 
213
  layout_->SetLeftAndRightPadding(LEFT_INTERNAL_PADDING.CP(scale), TEXT_INPUT_RIGHT_BORDER.CP(scale));
 
214
  layout_->SetSpaceBetweenChildren(SPACE_BETWEEN_ENTRY_AND_HIGHLIGHT.CP(scale));
 
215
 
 
216
  UpdateSize();
 
217
 
 
218
  hint_layout_->SetLeftAndRightPadding(HINT_PADDING.CP(scale), HINT_PADDING.CP(scale));
 
219
  hint_->SetScale(scale);
 
220
  hint_->SetMaximumHeight(pango_entry_->GetMinimumHeight());
 
221
 
 
222
  spinner_->scale = scale;
 
223
  activator_->SetTexture(LoadActivatorIcon(DEFAULT_ICON_SIZE.CP(scale)));
 
224
  warning_->SetTexture(LoadWarningIcon(DEFAULT_ICON_SIZE.CP(scale)));
 
225
  warning_tooltip_.Release();
 
226
 
 
227
  QueueRelayout();
 
228
  QueueDraw();
 
229
}
 
230
 
190
231
void TextInput::CheckIfCapsLockOn()
191
232
{
192
233
  GdkKeymap* keymap = gdk_keymap_get_default();
196
237
void TextInput::SetSpinnerVisible(bool visible)
197
238
{
198
239
  spinner_->SetVisible(visible);
199
 
 
200
 
  if (visible)
201
 
    activator_->SetVisible(false);
202
 
  else
203
 
    activator_->SetVisible(show_activator());
 
240
  activator_->SetVisible(!visible && show_activator());
204
241
}
205
242
 
206
243
void TextInput::SetSpinnerState(SpinnerState spinner_state)
268
305
  std::shared_ptr<PangoFontDescription> desc(pango_font_description_from_string(font_name), pango_font_description_free);
269
306
  pango_context_set_font_description(context, desc.get());
270
307
  pango_context_set_language(context, gtk_get_default_language());
 
308
  pango_cairo_context_set_resolution(context, 96.0 * Settings::Instance().font_scaling());
271
309
 
272
310
  pango_layout_set_height(layout, -1); //avoid wrap lines
273
311
  pango_layout_set_text(layout, _("Caps lock is on"), -1);
277
315
  extents.width  += TOOLTIP_OFFSET;
278
316
  extents.height += TOOLTIP_OFFSET;
279
317
 
280
 
  nux::CairoGraphics cg(CAIRO_FORMAT_ARGB32, extents.width, extents.height);
 
318
  nux::CairoGraphics cg(CAIRO_FORMAT_ARGB32, RawPixel(extents.width).CP(scale), RawPixel(extents.height).CP(scale));
 
319
  cairo_surface_set_device_scale(cg.GetSurface(), scale, scale);
281
320
  cairo_t* cr = cg.GetInternalContext();
282
321
 
283
322
  gtk_render_background(style_context, cr, 0, 0, extents.width, extents.height);
287
326
  warning_tooltip_ = texture_ptr_from_cairo_graphics(cg);
288
327
}
289
328
 
290
 
void TextInput::OnFontChanged(GtkSettings* settings, GParamSpec* pspec)
 
329
void TextInput::OnFontChanged()
291
330
{
292
331
  glib::String font_name;
293
332
  PangoFontDescription* desc;
294
333
 
295
 
  g_object_get(settings, "gtk-font-name", &font_name, NULL);
 
334
  g_object_get(gtk_settings_get_default(), "gtk-font-name", &font_name, NULL);
296
335
 
297
336
  desc = pango_font_description_from_string(font_name.Value());
298
337
  if (desc)
299
338
  {
300
339
    pango_entry_->SetFontFamily(pango_font_description_get_family(desc));
301
 
    pango_entry_->SetFontSize(PANGO_ENTRY_FONT_SIZE);
302
340
    pango_entry_->SetFontOptions(gdk_screen_get_font_options(gdk_screen_get_default()));
 
341
    UpdateSize();
303
342
 
304
343
    if (hint_font_name() == HINT_LABEL_DEFAULT_FONT_NAME)
305
344
    {
306
345
      std::ostringstream font_desc;
307
346
      font_desc << pango_font_description_get_family(desc) << " " << hint_font_size();
308
347
      hint_->SetFont(font_desc.str().c_str());
309
 
      pango_font_description_free(desc);
310
348
    }
 
349
 
 
350
    pango_font_description_free(desc);
311
351
  }
312
352
}
313
353
 
355
395
 
356
396
  layout_->ProcessDraw(GfxContext, force_draw);
357
397
 
358
 
  if (caps_lock_on && mouse_over_warning_icon_)
359
 
      PaintWarningTooltip(GfxContext);
 
398
  if (caps_lock_on && warning_->IsMouseInside() && !tooltip_timeout_)
 
399
    PaintWarningTooltip(GfxContext);
360
400
 
361
401
  if (!IsFullRedraw())
362
402
  {
372
412
 
373
413
void TextInput::PaintWarningTooltip(nux::GraphicsEngine& graphics_engine)
374
414
{
375
 
  nux::Geometry warning_geo = warning_->GetGeometry();
376
 
 
377
 
  nux::Geometry tooltip_geo = {warning_geo.x - (warning_tooltip_->GetWidth() + TOOLTIP_OFFSET / 2),
378
 
                               warning_geo.y - TOOLTIP_Y_OFFSET,
 
415
  nux::Geometry const& warning_geo = warning_->GetGeometry();
 
416
 
 
417
  if (!warning_tooltip_.IsValid())
 
418
    LoadWarningTooltip();
 
419
 
 
420
  nux::Geometry tooltip_geo = {warning_geo.x - (warning_tooltip_->GetWidth() + TOOLTIP_OFFSET.CP(scale) / 2),
 
421
                               warning_geo.y - TOOLTIP_Y_OFFSET.CP(scale),
379
422
                               warning_tooltip_->GetWidth(),
380
423
                               warning_tooltip_->GetHeight()};
381
424
 
382
 
  nux::GetPainter().PushDrawLayer(graphics_engine, tooltip_geo, CreateWarningLayer(warning_tooltip_.GetPointer()));
 
425
  auto const& warning_layer = CreateWarningLayer(warning_tooltip_.GetPointer());
 
426
  nux::GetPainter().PushDrawLayer(graphics_engine, tooltip_geo, warning_layer.get());
383
427
}
384
428
 
385
429
void TextInput::UpdateBackground(bool force)
386
430
{
387
 
  int RADIUS = 5;
388
431
  nux::Geometry geo(GetGeometry());
389
432
 
390
 
  LOG_DEBUG(logger) << "height: "
391
 
  << geo.height << " - "
392
 
  << layout_->GetGeometry().height << " - "
393
 
  << pango_entry_->GetGeometry().height;
394
 
 
395
 
  if (geo.width == last_width_
396
 
      && geo.height == last_height_
397
 
      && force == false)
 
433
  if (geo.width == last_width_ && geo.height == last_height_ && !force)
398
434
    return;
399
435
 
400
436
  last_width_ = geo.width;
401
437
  last_height_ = geo.height;
402
438
 
403
439
  nux::CairoGraphics cairo_graphics(CAIRO_FORMAT_ARGB32, last_width_, last_height_);
 
440
  cairo_surface_set_device_scale(cairo_graphics.GetSurface(), scale, scale);
404
441
  cairo_t* cr = cairo_graphics.GetInternalContext();
405
442
 
406
443
  cairo_graphics.DrawRoundedRectangle(cr,
407
444
                                      1.0f,
408
445
                                      0.5, 0.5,
409
 
                                      RADIUS,
410
 
                                      last_width_ - 1, last_height_ - 1,
 
446
                                      BORDER_RADIUS,
 
447
                                      (last_width_/scale) - 1, (last_height_/scale) - 1,
411
448
                                      false);
412
449
 
413
450
  cairo_set_operator(cr, CAIRO_OPERATOR_SOURCE);
417
454
  cairo_set_source_rgba(cr, 1.0f, 1.0f, 1.0f, 0.7f);
418
455
  cairo_stroke(cr);
419
456
 
420
 
  nux::BaseTexture* texture2D = texture_from_cairo_graphics(cairo_graphics);
 
457
  auto texture2D = texture_ptr_from_cairo_graphics(cairo_graphics);
421
458
 
422
459
  nux::TexCoordXForm texxform;
423
460
  texxform.SetTexCoordType(nux::TexCoordXForm::OFFSET_COORD);
433
470
                                        nux::color::White,
434
471
                                        true,
435
472
                                        rop));
436
 
 
437
 
  texture2D->UnReference();
438
473
}
439
474
 
440
475
void TextInput::OnMouseButtonDown(int x, int y, unsigned long button, unsigned long key)