<commit_before>/* Copyright 2019 Stanford University
 *
 * Licensed under the Apache License, Version 2.0 (the "License");
 * you may not use this file except in compliance with the License.
 * You may obtain a copy of the License at
 *
 *     http://www.apache.org/licenses/LICENSE-2.0
 *
 * Unless required by applicable law or agreed to in writing, software
 * distributed under the License is distributed on an "AS IS" BASIS,
 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
 * See the License for the specific language governing permissions and
 * limitations under the License.
 */

#include <cstdio>
#include <cassert>
#include <cstdlib>
#include "legion.h"

using namespace Legion;

/*
 * In this example we illustrate how the Legion
 * programming model supports multiple partitions
 * of the same logical region and the benefits it
 * provides by allowing multiple views onto the
 * same logical region.  We compute a simple 5-point
 * 1D stencil using the standard formula:
 * f'(x) = (-f(x+2h) + 8f(x+h) - 8f(x-h) + f(x-2h))/12h
 * For simplicity we'll assume h=1.
 */

enum TaskIDs {
  TOP_LEVEL_TASK_ID,
  INIT_FIELD_TASK_ID,
  STENCIL_TASK_ID,
  CHECK_TASK_ID,
};

enum FieldIDs {
  FID_VAL,
  FID_DERIV,
};

// The standard initialize field task from earlier examples
void init_field_task(const Task *task,
                     const std::vector<PhysicalRegion> &regions,
                     Context ctx, Runtime *runtime)
{
  assert(regions.size() == 1);
  assert(task->regions.size() == 1);
  assert(task->regions[0].privilege_fields.size() == 1);

  FieldID fid = *(task->regions[0].privilege_fields.begin());
  const int point = task->index_point.point_data[0];
  printf("Initializing field %d for block %d...\n", fid, point);

  const FieldAccessor<WRITE_DISCARD,double,1> acc(regions[0], fid);

  Rect<1> rect = runtime->get_index_space_domain(ctx,
                  task->regions[0].region.get_index_space());
  for (PointInRectIterator<1> pir(rect); pir(); pir++)
    acc[*pir] = drand48();
}

// Our stencil tasks is interesting because it
// has both slow and fast versions depending
// on whether or not its bounds have been clamped.
void stencil_task(const Task *task,
                  const std::vector<PhysicalRegion> &regions,
                  Context ctx, Runtime *runtime)
{
  assert(regions.size() == 2);
  assert(task->regions.size() == 2);
  assert(task->regions[0].privilege_fields.size() == 1);
  assert(task->regions[1].privilege_fields.size() == 1);
  assert(task->arglen == sizeof(int));
  const int max_elements = *((const int*)task->args);
  const int point = task->index_point.point_data[0];

  FieldID read_fid = *(task->regions[0].privilege_fields.begin());
  FieldID write_fid = *(task->regions[1].privilege_fields.begin());

  const FieldAccessor<READ_ONLY,double,1> read_acc(regions[0], read_fid);
  const FieldAccessor<WRITE_DISCARD,double,1> write_acc(regions[1], write_fid);

  Rect<1> rect = runtime->get_index_space_domain(ctx,
                  task->regions[1].region.get_index_space());
  // If we are on the edges of the entire space we are
  // operating over, then we're going to do the slow
  // path which checks for clamping when necessary.
  // If not, then we can do the fast path without
  // any checks.
  if ((rect.lo[0] < 2) || (rect.hi[0] > (max_elements-3)))
  {
    printf("Running slow stencil path for point %d...\n", point);
    // Note in the slow path that there are checks which
    // perform clamps when necessary before reading values.
    for (PointInRectIterator<1> pir(rect); pir(); pir++)
    {
      double l2, l1, r1, r2;
      if (pir[0] < 2)
        l2 = read_acc[0];
      else
        l2 = read_acc[*pir - 2];
      if (pir[0] < 1)
        l1 = read_acc[0];
      else
        l1 = read_acc[*pir - 1];
      if (pir[0] > (max_elements-2))
        r1 = read_acc[max_elements-1];
      else
        r1 = read_acc[*pir + 1];
      if (pir[0] > (max_elements-3))
        r2 = read_acc[max_elements-1];
      else
        r2 = read_acc[*pir + 2];

      double result = (-l2 + 8.0*l1 - 8.0*r1 + r2) / 12.0;
      write_acc[*pir] = result;
    }
  }
  else
  {
    printf("Running fast stencil path for point %d...\n", point);
    // In the fast path, we don't need any checks
    for (PointInRectIterator<1> pir(rect); pir(); pir++)
    {
      double l2 = read_acc[*pir - 2];
      double l1 = read_acc[*pir - 1];
      double r1 = read_acc[*pir + 1];
      double r2 = read_acc[*pir + 2];

      double result = (-l2 + 8.0*l1 - 8.0*r1 + r2) / 12.0;
      write_acc[*pir] = result;
    }
  }
}

void check_task(const Task *task,
                const std::vector<PhysicalRegion> &regions,
                Context ctx, Runtime *runtime)
{
  assert(regions.size() == 2);
  assert(task->regions.size() == 2);
  assert(task->regions[0].privilege_fields.size() == 1);
  assert(task->regions[1].privilege_fields.size() == 1);
  assert(task->arglen == sizeof(int));
  const int max_elements = *((const int*)task->args);

  FieldID src_fid = *(task->regions[0].privilege_fields.begin());
  FieldID dst_fid = *(task->regions[1].privilege_fields.begin());

  const FieldAccessor<READ_ONLY,double,1> src_acc(regions[0], src_fid);
  const FieldAccessor<READ_ONLY,double,1> dst_acc(regions[1], dst_fid);

  Rect<1> rect = runtime->get_index_space_domain(ctx,
                  task->regions[1].region.get_index_space());

  // This is the checking task so we can just do the slow path
  bool all_passed = true;
  for (PointInRectIterator<1> pir(rect); pir(); pir++)
  {
    double l2, l1, r1, r2;
    if (pir[0] < 2)
      l2 = src_acc[0];
    else
      l2 = src_acc[*pir - 2];
    if (pir[0] < 1)
      l1 = src_acc[0];
    else
      l1 = src_acc[*pir - 1];
    if (pir[0] > (max_elements-2))
      r1 = src_acc[max_elements-1];
    else
      r1 = src_acc[*pir + 1];
    if (pir[0] > (max_elements-3))
      r2 = src_acc[max_elements-1];
    else
      r2 = src_acc[*pir + 2];

    double expected = (-l2 + 8.0*l1 - 8.0*r1 + r2) / 12.0;
    double received = dst_acc[*pir];
    // Probably shouldn't bitwise compare floating point
    // numbers but the order of operations are the same so they
    // should be bitwise equal.
    if (expected != received)
      all_passed = false;
  }
  if (all_passed)
    printf("SUCCESS!\n");
  else
    printf("FAILURE!\n");
}

int main(int argc, char **argv)
{
  // Perform the registrations for our task variants first
  {
    TaskVariantRegistrar registrar(INIT_FIELD_TASK_ID, "init_field");
    registrar.add_constraint(ProcessorConstraint(Processor::LOC_PROC));
    registrar.set_leaf();
    Runtime::preregister_task_variant<init_field_task>(registrar, "init_field");
  }
  {
    TaskVariantRegistrar registrar(STENCIL_TASK_ID, "stencil");
    registrar.add_constraint(ProcessorConstraint(Processor::LOC_PROC));
    registrar.set_leaf();
    Runtime::preregister_task_variant<stencil_task>(registrar, "stencil");
  }
  {
    TaskVariantRegistrar registrar(CHECK_TASK_ID, "check");
    registrar.add_constraint(ProcessorConstraint(Processor::LOC_PROC));
    registrar.set_leaf();
    Runtime::preregister_task_variant<check_task>(registrar, "check");
  }
  // Then we can do the implicit start of the runtime
  Context ctx = Runtime::start_implicit(argc, argv, TOP_LEVEL_TASK_ID,
                                        Processor::LOC_PROC, "top_level",
                                        true/*control replicable*/);
  // Get the runtime now that we've started it
  Runtime *runtime = Runtime::get_runtime();
  // Run the normal stencil program
  int num_elements = 1024;
  int num_subregions = 4;
  // Check for any command line arguments
  for (int i = 1; i < argc; i++)
  {
    if (!strcmp(argv[i],"-n"))
      num_elements = atoi(argv[++i]);
    if (!strcmp(argv[i],"-b"))
      num_subregions = atoi(argv[++i]);
  }
  printf("Running stencil computation for %d elements...\n", num_elements);
  printf("Partitioning data into %d sub-regions...\n", num_subregions);

  Rect<1> elem_rect(0,num_elements-1);
  IndexSpaceT<1> is = runtime->create_index_space(ctx, elem_rect);
  FieldSpace fs = runtime->create_field_space(ctx);
  {
    FieldAllocator allocator =
      runtime->create_field_allocator(ctx, fs);
    allocator.allocate_field(sizeof(double),FID_VAL);
    allocator.allocate_field(sizeof(double),FID_DERIV);
  }
  LogicalRegion stencil_lr = runtime->create_logical_region(ctx, is, fs);

  Rect<1> color_bounds(0,num_subregions-1);
  IndexSpaceT<1> color_is = runtime->create_index_space(ctx, color_bounds);

  IndexPartition disjoint_ip =
    runtime->create_equal_partition(ctx, is, color_is);
  const int block_size = (num_elements + num_subregions - 1) / num_subregions;
  Transform<1,1> transform;
  transform[0][0] = block_size;
  Rect<1> extent(-2, block_size + 1);
  IndexPartition ghost_ip =
    runtime->create_partition_by_restriction(ctx, is, color_is, transform, extent);

  LogicalPartition disjoint_lp =
    runtime->get_logical_partition(ctx, stencil_lr, disjoint_ip);
  LogicalPartition ghost_lp =
    runtime->get_logical_partition(ctx, stencil_lr, ghost_ip);

  ArgumentMap arg_map;

  IndexLauncher init_launcher(INIT_FIELD_TASK_ID, color_is,
                              TaskArgument(NULL, 0), arg_map);
  init_launcher.add_region_requirement(
      RegionRequirement(disjoint_lp, 0/*projection ID*/,
                        WRITE_DISCARD, EXCLUSIVE, stencil_lr));
  init_launcher.add_field(0, FID_VAL);
  runtime->execute_index_space(ctx, init_launcher);

  IndexLauncher stencil_launcher(STENCIL_TASK_ID, color_is,
       TaskArgument(&num_elements, sizeof(num_elements)), arg_map);
  stencil_launcher.add_region_requirement(
      RegionRequirement(ghost_lp, 0/*projection ID*/,
                        READ_ONLY, EXCLUSIVE, stencil_lr));
  stencil_launcher.add_field(0, FID_VAL);
  stencil_launcher.add_region_requirement(
      RegionRequirement(disjoint_lp, 0/*projection ID*/,
                        READ_WRITE, EXCLUSIVE, stencil_lr));
  stencil_launcher.add_field(1, FID_DERIV);
  runtime->execute_index_space(ctx, stencil_launcher);

  TaskLauncher check_launcher(CHECK_TASK_ID,
      TaskArgument(&num_elements, sizeof(num_elements)));
  check_launcher.add_region_requirement(
      RegionRequirement(stencil_lr, READ_ONLY, EXCLUSIVE, stencil_lr));
  check_launcher.add_field(0, FID_VAL);
  check_launcher.add_region_requirement(
      RegionRequirement(stencil_lr, READ_ONLY, EXCLUSIVE, stencil_lr));
  check_launcher.add_field(1, FID_DERIV);
  runtime->execute_task(ctx, check_launcher);

  runtime->destroy_logical_region(ctx, stencil_lr);
  runtime->destroy_field_space(ctx, fs);
  runtime->destroy_index_space(ctx, is);

  // Mark that we are done excecuting the top-level task
  // After this call the context is no longer valid
  Runtime::finish_implicit(ctx);
  // The previous call is asynchronous so we still need to
  // wait for the shutdown of the runtime to complete
  return Runtime::wait_for_shutdown();
}
<commit_msg>examples: fixes for implicit top level task example<commit_after>/* Copyright 2019 Stanford University
 *
 * Licensed under the Apache License, Version 2.0 (the "License");
 * you may not use this file except in compliance with the License.
 * You may obtain a copy of the License at
 *
 *     http://www.apache.org/licenses/LICENSE-2.0
 *
 * Unless required by applicable law or agreed to in writing, software
 * distributed under the License is distributed on an "AS IS" BASIS,
 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
 * See the License for the specific language governing permissions and
 * limitations under the License.
 */

#include <cstdio>
#include <cassert>
#include <cstdlib>
#include "legion.h"

using namespace Legion;

/*
 * In this example we illustrate how the Legion
 * programming model supports multiple partitions
 * of the same logical region and the benefits it
 * provides by allowing multiple views onto the
 * same logical region.  We compute a simple 5-point
 * 1D stencil using the standard formula:
 * f'(x) = (-f(x+2h) + 8f(x+h) - 8f(x-h) + f(x-2h))/12h
 * For simplicity we'll assume h=1.
 */

enum TaskIDs {
  TOP_LEVEL_TASK_ID,
  INIT_FIELD_TASK_ID,
  STENCIL_TASK_ID,
  CHECK_TASK_ID,
};

enum FieldIDs {
  FID_VAL,
  FID_DERIV,
};

// The standard initialize field task from earlier examples
void init_field_task(const Task *task,
                     const std::vector<PhysicalRegion> &regions,
                     Context ctx, Runtime *runtime)
{
  assert(regions.size() == 1);
  assert(task->regions.size() == 1);
  assert(task->regions[0].privilege_fields.size() == 1);

  FieldID fid = *(task->regions[0].privilege_fields.begin());
  const int point = task->index_point.point_data[0];
  printf("Initializing field %d for block %d...\n", fid, point);

  const FieldAccessor<WRITE_DISCARD,double,1> acc(regions[0], fid);

  Rect<1> rect = runtime->get_index_space_domain(ctx,
                  task->regions[0].region.get_index_space());
  for (PointInRectIterator<1> pir(rect); pir(); pir++)
    acc[*pir] = drand48();
}

// Our stencil tasks is interesting because it
// has both slow and fast versions depending
// on whether or not its bounds have been clamped.
void stencil_task(const Task *task,
                  const std::vector<PhysicalRegion> &regions,
                  Context ctx, Runtime *runtime)
{
  assert(regions.size() == 2);
  assert(task->regions.size() == 2);
  assert(task->regions[0].privilege_fields.size() == 1);
  assert(task->regions[1].privilege_fields.size() == 1);
  assert(task->arglen == sizeof(int));
  const int max_elements = *((const int*)task->args);
  const int point = task->index_point.point_data[0];

  FieldID read_fid = *(task->regions[0].privilege_fields.begin());
  FieldID write_fid = *(task->regions[1].privilege_fields.begin());

  const FieldAccessor<READ_ONLY,double,1> read_acc(regions[0], read_fid);
  const FieldAccessor<WRITE_DISCARD,double,1> write_acc(regions[1], write_fid);

  Rect<1> rect = runtime->get_index_space_domain(ctx,
                  task->regions[1].region.get_index_space());
  // If we are on the edges of the entire space we are
  // operating over, then we're going to do the slow
  // path which checks for clamping when necessary.
  // If not, then we can do the fast path without
  // any checks.
  if ((rect.lo[0] < 2) || (rect.hi[0] > (max_elements-3)))
  {
    printf("Running slow stencil path for point %d...\n", point);
    // Note in the slow path that there are checks which
    // perform clamps when necessary before reading values.
    for (PointInRectIterator<1> pir(rect); pir(); pir++)
    {
      double l2, l1, r1, r2;
      if (pir[0] < 2)
        l2 = read_acc[0];
      else
        l2 = read_acc[*pir - 2];
      if (pir[0] < 1)
        l1 = read_acc[0];
      else
        l1 = read_acc[*pir - 1];
      if (pir[0] > (max_elements-2))
        r1 = read_acc[max_elements-1];
      else
        r1 = read_acc[*pir + 1];
      if (pir[0] > (max_elements-3))
        r2 = read_acc[max_elements-1];
      else
        r2 = read_acc[*pir + 2];

      double result = (-l2 + 8.0*l1 - 8.0*r1 + r2) / 12.0;
      write_acc[*pir] = result;
    }
  }
  else
  {
    printf("Running fast stencil path for point %d...\n", point);
    // In the fast path, we don't need any checks
    for (PointInRectIterator<1> pir(rect); pir(); pir++)
    {
      double l2 = read_acc[*pir - 2];
      double l1 = read_acc[*pir - 1];
      double r1 = read_acc[*pir + 1];
      double r2 = read_acc[*pir + 2];

      double result = (-l2 + 8.0*l1 - 8.0*r1 + r2) / 12.0;
      write_acc[*pir] = result;
    }
  }
}

void check_task(const Task *task,
                const std::vector<PhysicalRegion> &regions,
                Context ctx, Runtime *runtime)
{
  assert(regions.size() == 2);
  assert(task->regions.size() == 2);
  assert(task->regions[0].privilege_fields.size() == 1);
  assert(task->regions[1].privilege_fields.size() == 1);
  assert(task->arglen == sizeof(int));
  const int max_elements = *((const int*)task->args);

  FieldID src_fid = *(task->regions[0].privilege_fields.begin());
  FieldID dst_fid = *(task->regions[1].privilege_fields.begin());

  const FieldAccessor<READ_ONLY,double,1> src_acc(regions[0], src_fid);
  const FieldAccessor<READ_ONLY,double,1> dst_acc(regions[1], dst_fid);

  Rect<1> rect = runtime->get_index_space_domain(ctx,
                  task->regions[1].region.get_index_space());

  // This is the checking task so we can just do the slow path
  bool all_passed = true;
  for (PointInRectIterator<1> pir(rect); pir(); pir++)
  {
    double l2, l1, r1, r2;
    if (pir[0] < 2)
      l2 = src_acc[0];
    else
      l2 = src_acc[*pir - 2];
    if (pir[0] < 1)
      l1 = src_acc[0];
    else
      l1 = src_acc[*pir - 1];
    if (pir[0] > (max_elements-2))
      r1 = src_acc[max_elements-1];
    else
      r1 = src_acc[*pir + 1];
    if (pir[0] > (max_elements-3))
      r2 = src_acc[max_elements-1];
    else
      r2 = src_acc[*pir + 2];

    double expected = (-l2 + 8.0*l1 - 8.0*r1 + r2) / 12.0;
    double received = dst_acc[*pir];
    // Probably shouldn't bitwise compare floating point
    // numbers but the order of operations are the same so they
    // should be bitwise equal.
    if (expected != received)
      all_passed = false;
  }
  if (all_passed)
    printf("SUCCESS!\n");
  else
    printf("FAILURE!\n");
}

int main(int argc, char **argv)
{
  // Perform the registrations for our task variants first
  {
    TaskVariantRegistrar registrar(INIT_FIELD_TASK_ID, "init_field");
    registrar.add_constraint(ProcessorConstraint(Processor::LOC_PROC));
    registrar.set_leaf();
    Runtime::preregister_task_variant<init_field_task>(registrar, "init_field");
  }
  {
    TaskVariantRegistrar registrar(STENCIL_TASK_ID, "stencil");
    registrar.add_constraint(ProcessorConstraint(Processor::LOC_PROC));
    registrar.set_leaf();
    Runtime::preregister_task_variant<stencil_task>(registrar, "stencil");
  }
  {
    TaskVariantRegistrar registrar(CHECK_TASK_ID, "check");
    registrar.add_constraint(ProcessorConstraint(Processor::LOC_PROC));
    registrar.set_leaf();
    Runtime::preregister_task_variant<check_task>(registrar, "check");
  }
  // Then we can do the implicit start of the runtime
  Context ctx = Runtime::start_implicit(argc, argv, TOP_LEVEL_TASK_ID,
                                        Processor::LOC_PROC, "top_level",
                                        true/*control replicable*/);
  // Get the runtime now that we've started it
  Runtime *runtime = Runtime::get_runtime();
  // Run the normal stencil program
  int num_elements = 1024;
  int num_subregions = 4;
  // Check for any command line arguments
  for (int i = 1; i < argc; i++)
  {
    if (!strcmp(argv[i],"-n"))
      num_elements = atoi(argv[++i]);
    if (!strcmp(argv[i],"-b"))
      num_subregions = atoi(argv[++i]);
  }
  printf("Running stencil computation for %d elements...\n", num_elements);
  printf("Partitioning data into %d sub-regions...\n", num_subregions);

  Rect<1> elem_rect(0,num_elements-1);
  IndexSpaceT<1> is = runtime->create_index_space(ctx, elem_rect);
  FieldSpace fs = runtime->create_field_space(ctx);
  {
    FieldAllocator allocator =
      runtime->create_field_allocator(ctx, fs);
    allocator.allocate_field(sizeof(double),FID_VAL);
    allocator.allocate_field(sizeof(double),FID_DERIV);
  }
  LogicalRegion stencil_lr = runtime->create_logical_region(ctx, is, fs);

  Rect<1> color_bounds(0,num_subregions-1);
  IndexSpaceT<1> color_is = runtime->create_index_space(ctx, color_bounds);

  IndexPartition disjoint_ip =
    runtime->create_equal_partition(ctx, is, color_is);
  const int block_size = (num_elements + num_subregions - 1) / num_subregions;
  Transform<1,1> transform;
  transform[0][0] = block_size;
  Rect<1> extent(-2, block_size + 1);
  IndexPartition ghost_ip =
    runtime->create_partition_by_restriction(ctx, is, color_is, transform, extent);

  LogicalPartition disjoint_lp =
    runtime->get_logical_partition(ctx, stencil_lr, disjoint_ip);
  LogicalPartition ghost_lp =
    runtime->get_logical_partition(ctx, stencil_lr, ghost_ip);

  ArgumentMap arg_map;

  IndexLauncher init_launcher(INIT_FIELD_TASK_ID, color_is,
                              TaskArgument(NULL, 0), arg_map);
  init_launcher.add_region_requirement(
      RegionRequirement(disjoint_lp, 0/*projection ID*/,
                        WRITE_DISCARD, EXCLUSIVE, stencil_lr));
  init_launcher.add_field(0, FID_VAL);
  runtime->execute_index_space(ctx, init_launcher);

  IndexLauncher stencil_launcher(STENCIL_TASK_ID, color_is,
       TaskArgument(&num_elements, sizeof(num_elements)), arg_map);
  stencil_launcher.add_region_requirement(
      RegionRequirement(ghost_lp, 0/*projection ID*/,
                        READ_ONLY, EXCLUSIVE, stencil_lr));
  stencil_launcher.add_field(0, FID_VAL);
  stencil_launcher.add_region_requirement(
      RegionRequirement(disjoint_lp, 0/*projection ID*/,
                        WRITE_DISCARD, EXCLUSIVE, stencil_lr));
  stencil_launcher.add_field(1, FID_DERIV);
  runtime->execute_index_space(ctx, stencil_launcher);

  TaskLauncher check_launcher(CHECK_TASK_ID,
      TaskArgument(&num_elements, sizeof(num_elements)));
  check_launcher.add_region_requirement(
      RegionRequirement(stencil_lr, READ_ONLY, EXCLUSIVE, stencil_lr));
  check_launcher.add_field(0, FID_VAL);
  check_launcher.add_region_requirement(
      RegionRequirement(stencil_lr, READ_ONLY, EXCLUSIVE, stencil_lr));
  check_launcher.add_field(1, FID_DERIV);
  runtime->execute_task(ctx, check_launcher);

  runtime->destroy_logical_region(ctx, stencil_lr);
  runtime->destroy_field_space(ctx, fs);
  runtime->destroy_index_space(ctx, is);
  runtime->destroy_index_space(ctx, color_is);

  // Mark that we are done excecuting the top-level task
  // After this call the context is no longer valid
  Runtime::finish_implicit(ctx);
  // The previous call is asynchronous so we still need to
  // wait for the shutdown of the runtime to complete
  return Runtime::wait_for_shutdown();
}
<|endoftext|>


<commit_before>// friend class as template parameter

// originally found in package 'zipios'

// typechecking results:
//   errors:   0
//   warnings: 0
// error: k0069.cc:15:12: internal error: found dependent type `Friend' in non-template

// ERR-MATCH: internal error: found dependent type `[^(].*?' in non-template

template< class Type > struct T {
  friend struct Friend ;
};

struct Friend;

typedef T< Friend > T1 ;
<commit_msg>Undo previous - hard to distinguish errors<commit_after>// friend class as template parameter

// originally found in package 'zipios'

// typechecking results:
//   errors:   0
//   warnings: 0
// error: k0069.cc:15:12: internal error: found dependent type `Friend' in non-template

// ERR-MATCH: internal error: found dependent type `.*?' in non-template

template< class Type > struct T {
  friend struct Friend ;
};

struct Friend;

typedef T< Friend > T1 ;
<|endoftext|>


<commit_before>//
// Copyright RIME Developers
// Distributed under the BSD License
//
// 2011-10-23 GONG Chen <chen.sst@gmail.com>
//
#include <cctype>
#include <rime/common.h>
#include <rime/composition.h>
#include <rime/context.h>
#include <rime/engine.h>
#include <rime/key_table.h>
#include <rime/gear/editor.h>
#include <rime/gear/translator_commons.h>

namespace rime {

static struct EditorActionDef {
  const char* name;
  Editor::HandlerPtr action;
} editor_action_definitions[] = {
  { "confirm",  &Editor::Confirm },
  { "commit_comment", &Editor::CommitComment },
  { "commit_raw_input", &Editor::CommitRawInput },
  { "commit_script_text", &Editor::CommitScriptText },
  { "commit_composition", &Editor::CommitComposition },
  { "revert", &Editor::RevertLastEdit },
  { "back", &Editor::BackToPreviousInput },
  { "back_syllable", &Editor::BackToPreviousSyllable },
  { "delete_candidate", &Editor::DeleteCandidate },
  { "delete", &Editor::DeleteChar },
  { "cancel", &Editor::CancelComposition },
  { "noop", nullptr }
};

static struct EditorCharHandlerDef {
  const char* name;
  Editor::CharHandlerPtr action;
} editor_char_handler_definitions[] = {
  { "direct_commit", &Editor::DirectCommit },
  { "add_to_input", &Editor::AddToInput },
  { "noop", nullptr }
};

Editor::Editor(const Ticket& ticket, bool auto_commit) : Processor(ticket) {
  engine_->context()->set_option("_auto_commit", auto_commit);
}

ProcessResult Editor::ProcessKeyEvent(const KeyEvent& key_event) {
  if (key_event.release())
    return kRejected;
  int ch = key_event.keycode();
  Context* ctx = engine_->context();
  if (ctx->IsComposing()) {
    if (Accept(key_event)) {
      return kAccepted;
    }
    if (key_event.ctrl() || key_event.alt()) {
      return kNoop;
    }
    if (key_event.shift()) {
      KeyEvent shift_as_ctrl{
          key_event.keycode(),
          (key_event.modifier() & ~kShiftMask) | kControlMask
      };
      if (Accept(shift_as_ctrl)) {
        return kAccepted;
      }
      KeyEvent remove_shift{
          key_event.keycode(),
          key_event.modifier() & ~kShiftMask
      };
      if (Accept(remove_shift)) {
        return kAccepted;
      }
    }
  }
  if (char_handler_ &&
      !key_event.ctrl() && !key_event.alt() &&
      ch > 0x20 && ch < 0x7f) {
    DLOG(INFO) << "input char: '" << (char)ch << "', " << ch
               << ", '" << key_event.repr() << "'";
    return RIME_THIS_CALL(char_handler_)(ctx, ch);
  }
  // not handled
  return kNoop;
}

bool Editor::Accept(const KeyEvent& key_event) {
  auto binding = key_bindings_.find(key_event);
  if (binding != key_bindings_.end()) {
    auto action = binding->second;
    RIME_THIS_CALL(action)(engine_->context());
    DLOG(INFO) << "editor action key accepted: " << key_event.repr();
    return true;
  }
  return false;
}

void Editor::Bind(KeyEvent key_event, HandlerPtr action) {
  key_bindings_[key_event] = action;
}

void Editor::LoadConfig() {
  // TODO
}

void Editor::Confirm(Context* ctx) {
  ctx->ConfirmCurrentSelection() || ctx->Commit();
}

void Editor::CommitComment(Context* ctx) {
  // TODO
}

void Editor::CommitScriptText(Context* ctx) {
  engine_->sink()(ctx->GetScriptText());
  ctx->Clear();
}

void Editor::CommitRawInput(Context* ctx) {
  ctx->ClearNonConfirmedComposition();
  ctx->Commit();
}

void Editor::CommitComposition(Context* ctx) {
  if (!ctx->ConfirmCurrentSelection() || !ctx->HasMenu())
    ctx->Commit();
}

void Editor::RevertLastEdit(Context* ctx) {
  // different behavior in regard to previous operation type
  ctx->ReopenPreviousSelection() ||
      (ctx->PopInput() && ctx->ReopenPreviousSegment());
}

void Editor::BackToPreviousInput(Context* ctx) {
  ctx->ReopenPreviousSegment() ||
      ctx->ReopenPreviousSelection() ||
      ctx->PopInput();
}

void Editor::BackToPreviousSyllable(Context* ctx) {
  size_t caret_pos = ctx->caret_pos();
  if (caret_pos == 0)
    return;
  const Composition* comp = ctx->composition();
  if (comp && !comp->empty()) {
    auto cand = comp->back().GetSelectedCandidate();
    auto phrase = As<Phrase>(Candidate::GetGenuineCandidate(cand));
    if (phrase && phrase->syllabification()) {
      size_t stop = phrase->syllabification()->PreviousStop(caret_pos);
      if (stop != caret_pos) {
        ctx->PopInput(caret_pos - stop);
        return;
      }
    }
  }
  ctx->PopInput();
}

void Editor::DeleteCandidate(Context* ctx) {
  ctx->DeleteCurrentSelection();
}

void Editor::DeleteChar(Context* ctx) {
  ctx->DeleteInput();
}

void Editor::CancelComposition(Context* ctx) {
  if (!ctx->ClearPreviousSegment())
    ctx->Clear();
}

ProcessResult Editor::DirectCommit(Context* ctx, int ch) {
  ctx->Commit();
  return kRejected;
}

ProcessResult Editor::AddToInput(Context* ctx, int ch) {
    ctx->PushInput(ch);
    ctx->ConfirmPreviousSelection();
    return kAccepted;
}

FluidEditor::FluidEditor(const Ticket& ticket) : Editor(ticket, false) {
  Bind({XK_space, 0}, &Editor::Confirm);
  Bind({XK_BackSpace, 0}, &Editor::BackToPreviousInput);  //
  Bind({XK_BackSpace, kControlMask}, &Editor::BackToPreviousSyllable);
  Bind({XK_Return, 0}, &Editor::CommitComposition);  //
  Bind({XK_Return, kControlMask}, &Editor::CommitRawInput);  //
  Bind({XK_Return, kShiftMask}, &Editor::CommitScriptText);  //
  Bind({XK_Return, kControlMask | kShiftMask}, &Editor::CommitComment);
  Bind({XK_Delete, 0}, &Editor::DeleteChar);
  Bind({XK_Delete, kControlMask}, &Editor::DeleteCandidate);
  Bind({XK_Escape, 0}, &Editor::CancelComposition);
  char_handler_ = &Editor::AddToInput;  //
  LoadConfig();
}

ExpressEditor::ExpressEditor(const Ticket& ticket) : Editor(ticket, true) {
  Bind({XK_space, 0}, &Editor::Confirm);
  Bind({XK_BackSpace, 0}, &Editor::RevertLastEdit);  //
  Bind({XK_BackSpace, kControlMask}, &Editor::BackToPreviousSyllable);
  Bind({XK_Return, 0}, &Editor::CommitRawInput);  //
  Bind({XK_Return, kControlMask}, &Editor::CommitScriptText);  //
  Bind({XK_Return, kControlMask | kShiftMask}, &Editor::CommitComment);
  Bind({XK_Delete, 0}, &Editor::DeleteChar);
  Bind({XK_Delete, kControlMask}, &Editor::DeleteCandidate);
  Bind({XK_Escape, 0}, &Editor::CancelComposition);
  char_handler_ = &Editor::DirectCommit;  //
  LoadConfig();
}

}  // namespace rime
<commit_msg>editor: load config.<commit_after>//
// Copyright RIME Developers
// Distributed under the BSD License
//
// 2011-10-23 GONG Chen <chen.sst@gmail.com>
//
#include <cctype>
#include <rime/common.h>
#include <rime/composition.h>
#include <rime/config.h>
#include <rime/context.h>
#include <rime/engine.h>
#include <rime/schema.h>
#include <rime/key_table.h>
#include <rime/gear/editor.h>
#include <rime/gear/translator_commons.h>

namespace rime {

static struct EditorActionDef {
  const char* name;
  Editor::HandlerPtr action;
} editor_action_definitions[] = {
  { "confirm",  &Editor::Confirm },
  { "commit_comment", &Editor::CommitComment },
  { "commit_raw_input", &Editor::CommitRawInput },
  { "commit_script_text", &Editor::CommitScriptText },
  { "commit_composition", &Editor::CommitComposition },
  { "revert", &Editor::RevertLastEdit },
  { "back", &Editor::BackToPreviousInput },
  { "back_syllable", &Editor::BackToPreviousSyllable },
  { "delete_candidate", &Editor::DeleteCandidate },
  { "delete", &Editor::DeleteChar },
  { "cancel", &Editor::CancelComposition },
  { "noop", nullptr }
};

static struct EditorCharHandlerDef {
  const char* name;
  Editor::CharHandlerPtr action;
} editor_char_handler_definitions[] = {
  { "direct_commit", &Editor::DirectCommit },
  { "add_to_input", &Editor::AddToInput },
  { "noop", nullptr }
};

Editor::Editor(const Ticket& ticket, bool auto_commit) : Processor(ticket) {
  engine_->context()->set_option("_auto_commit", auto_commit);
}

ProcessResult Editor::ProcessKeyEvent(const KeyEvent& key_event) {
  if (key_event.release())
    return kRejected;
  int ch = key_event.keycode();
  Context* ctx = engine_->context();
  if (ctx->IsComposing()) {
    if (Accept(key_event)) {
      return kAccepted;
    }
    if (key_event.ctrl() || key_event.alt()) {
      return kNoop;
    }
    if (key_event.shift()) {
      KeyEvent shift_as_ctrl{
          key_event.keycode(),
          (key_event.modifier() & ~kShiftMask) | kControlMask
      };
      if (Accept(shift_as_ctrl)) {
        return kAccepted;
      }
      KeyEvent remove_shift{
          key_event.keycode(),
          key_event.modifier() & ~kShiftMask
      };
      if (Accept(remove_shift)) {
        return kAccepted;
      }
    }
  }
  if (char_handler_ &&
      !key_event.ctrl() && !key_event.alt() &&
      ch > 0x20 && ch < 0x7f) {
    DLOG(INFO) << "input char: '" << (char)ch << "', " << ch
               << ", '" << key_event.repr() << "'";
    return RIME_THIS_CALL(char_handler_)(ctx, ch);
  }
  // not handled
  return kNoop;
}

bool Editor::Accept(const KeyEvent& key_event) {
  auto binding = key_bindings_.find(key_event);
  if (binding != key_bindings_.end()) {
    auto action = binding->second;
    RIME_THIS_CALL(action)(engine_->context());
    DLOG(INFO) << "editor action key accepted: " << key_event.repr();
    return true;
  }
  return false;
}

void Editor::Bind(KeyEvent key_event, HandlerPtr action) {
  if (action) {
    key_bindings_[key_event] = action;
  }
  else {
    key_bindings_.erase(key_event);
  }
}

void Editor::LoadConfig() {
  if (!engine_) {
    return;
  }
  Config* config = engine_->schema()->config();
  if (auto bindings = config->GetMap("editor/bindings")) {
    for (auto it = bindings->begin(); it != bindings->end(); ++it) {
      auto value = As<ConfigValue>(it->second);
      if (!value) {
        continue;
      }
      auto* p = editor_action_definitions;
      while (p->action && p->name != value->str()) {
        ++p;
      }
      if (!p->action && p->name != value->str()) {
        LOG(WARNING) << "invalid editor action: " << value->str();
        continue;
      }
      KeyEvent ke;
      if (!ke.Parse(it->first)) {
        LOG(WARNING) << "invalid edit key: " << it->first;
        continue;
      }
      Bind(ke, p->action);
    }
  }
  if (auto value = config->GetValue("editor/char_handler")) {
    auto* p = editor_char_handler_definitions;
    while (p->action && p->name != value->str()) {
      ++p;
    }
    if (!p->action && p->name != value->str()) {
      LOG(WARNING) << "invalid char_handler: " << value->str();
    }
    else {
      char_handler_ = p->action;
    }
  }
}

void Editor::Confirm(Context* ctx) {
  ctx->ConfirmCurrentSelection() || ctx->Commit();
}

void Editor::CommitComment(Context* ctx) {
  // TODO
}

void Editor::CommitScriptText(Context* ctx) {
  engine_->sink()(ctx->GetScriptText());
  ctx->Clear();
}

void Editor::CommitRawInput(Context* ctx) {
  ctx->ClearNonConfirmedComposition();
  ctx->Commit();
}

void Editor::CommitComposition(Context* ctx) {
  if (!ctx->ConfirmCurrentSelection() || !ctx->HasMenu())
    ctx->Commit();
}

void Editor::RevertLastEdit(Context* ctx) {
  // different behavior in regard to previous operation type
  ctx->ReopenPreviousSelection() ||
      (ctx->PopInput() && ctx->ReopenPreviousSegment());
}

void Editor::BackToPreviousInput(Context* ctx) {
  ctx->ReopenPreviousSegment() ||
      ctx->ReopenPreviousSelection() ||
      ctx->PopInput();
}

void Editor::BackToPreviousSyllable(Context* ctx) {
  size_t caret_pos = ctx->caret_pos();
  if (caret_pos == 0)
    return;
  const Composition* comp = ctx->composition();
  if (comp && !comp->empty()) {
    auto cand = comp->back().GetSelectedCandidate();
    auto phrase = As<Phrase>(Candidate::GetGenuineCandidate(cand));
    if (phrase && phrase->syllabification()) {
      size_t stop = phrase->syllabification()->PreviousStop(caret_pos);
      if (stop != caret_pos) {
        ctx->PopInput(caret_pos - stop);
        return;
      }
    }
  }
  ctx->PopInput();
}

void Editor::DeleteCandidate(Context* ctx) {
  ctx->DeleteCurrentSelection();
}

void Editor::DeleteChar(Context* ctx) {
  ctx->DeleteInput();
}

void Editor::CancelComposition(Context* ctx) {
  if (!ctx->ClearPreviousSegment())
    ctx->Clear();
}

ProcessResult Editor::DirectCommit(Context* ctx, int ch) {
  ctx->Commit();
  return kRejected;
}

ProcessResult Editor::AddToInput(Context* ctx, int ch) {
    ctx->PushInput(ch);
    ctx->ConfirmPreviousSelection();
    return kAccepted;
}

FluidEditor::FluidEditor(const Ticket& ticket) : Editor(ticket, false) {
  Bind({XK_space, 0}, &Editor::Confirm);
  Bind({XK_BackSpace, 0}, &Editor::BackToPreviousInput);  //
  Bind({XK_BackSpace, kControlMask}, &Editor::BackToPreviousSyllable);
  Bind({XK_Return, 0}, &Editor::CommitComposition);  //
  Bind({XK_Return, kControlMask}, &Editor::CommitRawInput);  //
  Bind({XK_Return, kShiftMask}, &Editor::CommitScriptText);  //
  Bind({XK_Return, kControlMask | kShiftMask}, &Editor::CommitComment);
  Bind({XK_Delete, 0}, &Editor::DeleteChar);
  Bind({XK_Delete, kControlMask}, &Editor::DeleteCandidate);
  Bind({XK_Escape, 0}, &Editor::CancelComposition);
  char_handler_ = &Editor::AddToInput;  //
  LoadConfig();
}

ExpressEditor::ExpressEditor(const Ticket& ticket) : Editor(ticket, true) {
  Bind({XK_space, 0}, &Editor::Confirm);
  Bind({XK_BackSpace, 0}, &Editor::RevertLastEdit);  //
  Bind({XK_BackSpace, kControlMask}, &Editor::BackToPreviousSyllable);
  Bind({XK_Return, 0}, &Editor::CommitRawInput);  //
  Bind({XK_Return, kControlMask}, &Editor::CommitScriptText);  //
  Bind({XK_Return, kControlMask | kShiftMask}, &Editor::CommitComment);
  Bind({XK_Delete, 0}, &Editor::DeleteChar);
  Bind({XK_Delete, kControlMask}, &Editor::DeleteCandidate);
  Bind({XK_Escape, 0}, &Editor::CancelComposition);
  char_handler_ = &Editor::DirectCommit;  //
  LoadConfig();
}

}  // namespace rime
<|endoftext|>


<commit_before>//
// Copyleft RIME Developers
// License: GPLv3
//
// 2013-01-02 GONG Chen <chen.sst@gmail.com>
//
#include <rime/candidate.h>
#include <rime/context.h>
#include <rime/composition.h>
#include <rime/engine.h>
#include <rime/key_event.h>
#include <rime/schema.h>
#include <rime/ticket.h>
#include <rime/dict/dictionary.h>
#include <rime/dict/user_dictionary.h>
#include <rime/gear/memory.h>
#include <rime/gear/translator_commons.h>

namespace rime {

void CommitEntry::Clear() {
  text.clear();
  code.clear();
  elements.clear();
}

void CommitEntry::AppendPhrase(const shared_ptr<Phrase>& phrase) {
  text += phrase->text();
  code.insert(code.end(),
              phrase->code().begin(), phrase->code().end());
  if (auto sentence = As<Sentence>(phrase)) {
    for (const DictEntry& e : sentence->components()) {
      elements.push_back(&e);
    }
  }
  else {
    elements.push_back(&phrase->entry());
  }
}

bool CommitEntry::Save() const {
  if (memory && !empty()) {
    DLOG(INFO) << "memorize commit entry: " << text;
    return memory->Memorize(*this);
  }
  return false;
}

Memory::Memory(const Ticket& ticket) {
  if (!ticket.engine)
    return;

  if (auto dictionary = Dictionary::Require("dictionary")) {
    dict_.reset(dictionary->Create(ticket));
    if (dict_)
      dict_->Load();
  }

  if (auto user_dictionary = UserDictionary::Require("user_dictionary")) {
    user_dict_.reset(user_dictionary->Create(ticket));
    if (user_dict_) {
      user_dict_->Load();
      if (dict_)
        user_dict_->Attach(dict_->table(), dict_->prism());
    }
  }

  Context* ctx = ticket.engine->context();
  commit_connection_ = ctx->commit_notifier().connect(
      [this](Context* ctx) { OnCommit(ctx); });
  delete_connection_ = ctx->delete_notifier().connect(
      [this](Context* ctx) { OnDeleteEntry(ctx); });
  unhandled_key_connection_ = ctx->unhandled_key_notifier().connect(
      [this](Context* ctx, const KeyEvent& key) { OnUnhandledKey(ctx, key); });
}

Memory::~Memory() {
  commit_connection_.disconnect();
  delete_connection_.disconnect();
  unhandled_key_connection_.disconnect();
}

bool Memory::StartSession() {
  return user_dict_->NewTransaction();
}

bool Memory::FinishSession() {
  return user_dict_->CommitPendingTransaction();
}

bool Memory::DiscardSession() {
  return user_dict_->RevertRecentTransaction();
}

void Memory::OnCommit(Context* ctx) {
  if (!user_dict_|| user_dict_->readonly())
    return;
  StartSession();
  CommitEntry commit_entry(this);
  for (auto& seg : *ctx->composition()) {
    auto phrase = As<Phrase>(Candidate::GetGenuineCandidate(
            seg.GetSelectedCandidate()));
    bool recognized = phrase && phrase->language() == language();
    if (recognized) {
      commit_entry.AppendPhrase(phrase);
    }
    if (!recognized || seg.status >= Segment::kConfirmed) {
      commit_entry.Save();
      commit_entry.Clear();
    }
  }
}

void Memory::OnDeleteEntry(Context* ctx) {
  if (!user_dict_ ||
      user_dict_->readonly() ||
      !ctx ||
      ctx->composition()->empty())
    return;
  Segment& seg(ctx->composition()->back());
  auto phrase = As<Phrase>(Candidate::GetGenuineCandidate(
          seg.GetSelectedCandidate()));
  bool recognized = phrase && phrase->language() == language();
  if (recognized) {
    const DictEntry& entry(phrase->entry());
    LOG(INFO) << "deleting entry: '" << entry.text << "'.";
    user_dict_->UpdateEntry(entry, -1);  // mark as deleted in user dict
    ctx->RefreshNonConfirmedComposition();
  }
}

void Memory::OnUnhandledKey(Context* ctx, const KeyEvent& key) {
  if (!user_dict_ || user_dict_->readonly())
    return;
  if ((key.modifier() & ~kShiftMask) == 0) {
    if (key.keycode() == XK_BackSpace && DiscardSession()) {
      return;  // forget about last commit
    }
    FinishSession();
  }
}

}  // namespace rime
<commit_msg>fix crash when set translator/enable_user_dict: false.<commit_after>//
// Copyleft RIME Developers
// License: GPLv3
//
// 2013-01-02 GONG Chen <chen.sst@gmail.com>
//
#include <rime/candidate.h>
#include <rime/context.h>
#include <rime/composition.h>
#include <rime/engine.h>
#include <rime/key_event.h>
#include <rime/schema.h>
#include <rime/ticket.h>
#include <rime/dict/dictionary.h>
#include <rime/dict/user_dictionary.h>
#include <rime/gear/memory.h>
#include <rime/gear/translator_commons.h>

namespace rime {

void CommitEntry::Clear() {
  text.clear();
  code.clear();
  elements.clear();
}

void CommitEntry::AppendPhrase(const shared_ptr<Phrase>& phrase) {
  text += phrase->text();
  code.insert(code.end(),
              phrase->code().begin(), phrase->code().end());
  if (auto sentence = As<Sentence>(phrase)) {
    for (const DictEntry& e : sentence->components()) {
      elements.push_back(&e);
    }
  }
  else {
    elements.push_back(&phrase->entry());
  }
}

bool CommitEntry::Save() const {
  if (memory && !empty()) {
    DLOG(INFO) << "memorize commit entry: " << text;
    return memory->Memorize(*this);
  }
  return false;
}

Memory::Memory(const Ticket& ticket) {
  if (!ticket.engine)
    return;

  if (auto dictionary = Dictionary::Require("dictionary")) {
    dict_.reset(dictionary->Create(ticket));
    if (dict_)
      dict_->Load();
  }

  if (auto user_dictionary = UserDictionary::Require("user_dictionary")) {
    user_dict_.reset(user_dictionary->Create(ticket));
    if (user_dict_) {
      user_dict_->Load();
      if (dict_)
        user_dict_->Attach(dict_->table(), dict_->prism());
    }
  }

  Context* ctx = ticket.engine->context();
  commit_connection_ = ctx->commit_notifier().connect(
      [this](Context* ctx) { OnCommit(ctx); });
  delete_connection_ = ctx->delete_notifier().connect(
      [this](Context* ctx) { OnDeleteEntry(ctx); });
  unhandled_key_connection_ = ctx->unhandled_key_notifier().connect(
      [this](Context* ctx, const KeyEvent& key) { OnUnhandledKey(ctx, key); });
}

Memory::~Memory() {
  commit_connection_.disconnect();
  delete_connection_.disconnect();
  unhandled_key_connection_.disconnect();
}

bool Memory::StartSession() {
  return user_dict_ && user_dict_->NewTransaction();
}

bool Memory::FinishSession() {
  return user_dict_ && user_dict_->CommitPendingTransaction();
}

bool Memory::DiscardSession() {
  return user_dict_ && user_dict_->RevertRecentTransaction();
}

void Memory::OnCommit(Context* ctx) {
  if (!user_dict_|| user_dict_->readonly())
    return;
  StartSession();
  CommitEntry commit_entry(this);
  for (auto& seg : *ctx->composition()) {
    auto phrase = As<Phrase>(Candidate::GetGenuineCandidate(
            seg.GetSelectedCandidate()));
    bool recognized = phrase && phrase->language() == language();
    if (recognized) {
      commit_entry.AppendPhrase(phrase);
    }
    if (!recognized || seg.status >= Segment::kConfirmed) {
      commit_entry.Save();
      commit_entry.Clear();
    }
  }
}

void Memory::OnDeleteEntry(Context* ctx) {
  if (!user_dict_ ||
      user_dict_->readonly() ||
      !ctx ||
      ctx->composition()->empty())
    return;
  Segment& seg(ctx->composition()->back());
  auto phrase = As<Phrase>(Candidate::GetGenuineCandidate(
          seg.GetSelectedCandidate()));
  bool recognized = phrase && phrase->language() == language();
  if (recognized) {
    const DictEntry& entry(phrase->entry());
    LOG(INFO) << "deleting entry: '" << entry.text << "'.";
    user_dict_->UpdateEntry(entry, -1);  // mark as deleted in user dict
    ctx->RefreshNonConfirmedComposition();
  }
}

void Memory::OnUnhandledKey(Context* ctx, const KeyEvent& key) {
  if (!user_dict_ || user_dict_->readonly())
    return;
  if ((key.modifier() & ~kShiftMask) == 0) {
    if (key.keycode() == XK_BackSpace && DiscardSession()) {
      return;  // forget about last commit
    }
    FinishSession();
  }
}

}  // namespace rime
<|endoftext|>


<commit_before>/* HIT_START
 * BUILD: %t %s ../test_common.cpp
 * RUN: %t
 * HIT_END
 */
#include <stdlib.h>
#include <stdio.h>
#include <string.h>

#include <hip/hip_runtime.h>
#include "test_common.h"
texture<float, 2, hipReadModeElementType> tex;

bool testResult = true;

__global__ void tex2DKernel(float* outputData,
#ifdef __HIP_PLATFORM_HCC__
                            hipTextureObject_t textureObject,
#endif
                            int width, int height) {
    int x = blockIdx.x * blockDim.x + threadIdx.x;
    int y = blockIdx.y * blockDim.y + threadIdx.y;
#ifdef __HIP_PLATFORM_HCC__
    outputData[y * width + x] = tex2D(tex, textureObject, x, y);
#else
    outputData[y * width + x] = tex2D(tex, x, y);
#endif
}

void runTest(int argc, char** argv);

int main(int argc, char** argv) {
    runTest(argc, argv);
    if (testResult) {
        passed();
    } else {
        exit(EXIT_FAILURE);
    }
}

void runTest(int argc, char** argv) {
    unsigned int width = 256;
    unsigned int height = 256;
    unsigned int size = width * height * sizeof(float);
    float* hData = (float*)malloc(size);
    memset(hData, 0, size);
    for (int i = 0; i < height; i++) {
        for (int j = 0; j < width; j++) {
            hData[i * width + j] = i * width + j;
        }
    }
    printf("hData: ");
    for (int i = 0; i < 64; i++) {
        printf("%f  ", hData[i]);
    }
    printf("\n");

    hipChannelFormatDesc channelDesc = hipCreateChannelDesc(32, 0, 0, 0, hipChannelFormatKindFloat);
    hipArray* hipArray;
    hipMallocArray(&hipArray, &channelDesc, width, height);

    hipMemcpyToArray(hipArray, 0, 0, hData, size, hipMemcpyHostToDevice);

    tex.addressMode[0] = hipAddressModeWrap;
    tex.addressMode[1] = hipAddressModeWrap;
    tex.filterMode = hipFilterModePoint;
    tex.normalized = 0;

    hipBindTextureToArray(tex, hipArray, channelDesc);

    float* dData = NULL;
    hipMalloc((void**)&dData, size);

    dim3 dimBlock(16, 16, 1);
    dim3 dimGrid(width / dimBlock.x, height / dimBlock.y, 1);
#ifdef __HIP_PLATFORM_HCC__
    hipLaunchKernelGGL(tex2DKernel, dim3(dimGrid), dim3(dimBlock), 0, 0, dData, tex.textureObject,
                       width, height);
#else
    hipLaunchKernelGGL(tex2DKernel, dim3(dimGrid), dim3(dimBlock), 0, 0, dData, width, height);
#endif
    hipDeviceSynchronize();

    float* hOutputData = (float*)malloc(size);
    memset(hOutputData, 0, size);
    hipMemcpy(hOutputData, dData, size, hipMemcpyDeviceToHost);

    printf("dData: ");
    for (int i = 0; i < 64; i++) {
        printf("%f  ", hOutputData[i]);
    }
    printf("\n");
    for (int i = 0; i < height; i++) {
        for (int j = 0; j < width; j++) {
            if (hData[i * width + j] != hOutputData[i * width + j]) {
                printf("Difference [ %d %d ]:%f ----%f\n", i, j, hData[i * width + j],
                       hOutputData[i * width + j]);
                testResult = false;
                break;
            }
        }
    }
    hipFree(dData);
    hipFreeArray(hipArray);
}
<commit_msg>Remove textureObj kernel argument for HIP/HCC path<commit_after>/* HIT_START
 * BUILD: %t %s ../test_common.cpp
 * RUN: %t
 * HIT_END
 */
#include <stdlib.h>
#include <stdio.h>
#include <string.h>

#include <hip/hip_runtime.h>
#include "test_common.h"
texture<float, 2, hipReadModeElementType> tex;

bool testResult = true;

__global__ void tex2DKernel(float* outputData,
                            int width, int height) {
    int x = blockIdx.x * blockDim.x + threadIdx.x;
    int y = blockIdx.y * blockDim.y + threadIdx.y;
    outputData[y * width + x] = tex2D(tex, x, y);
}

void runTest(int argc, char** argv);

int main(int argc, char** argv) {
    runTest(argc, argv);
    if (testResult) {
        passed();
    } else {
        exit(EXIT_FAILURE);
    }
}

void runTest(int argc, char** argv) {
    unsigned int width = 256;
    unsigned int height = 256;
    unsigned int size = width * height * sizeof(float);
    float* hData = (float*)malloc(size);
    memset(hData, 0, size);
    for (int i = 0; i < height; i++) {
        for (int j = 0; j < width; j++) {
            hData[i * width + j] = i * width + j;
        }
    }
    printf("hData: ");
    for (int i = 0; i < 64; i++) {
        printf("%f  ", hData[i]);
    }
    printf("\n");

    hipChannelFormatDesc channelDesc = hipCreateChannelDesc(32, 0, 0, 0, hipChannelFormatKindFloat);
    hipArray* hipArray;
    hipMallocArray(&hipArray, &channelDesc, width, height);

    hipMemcpyToArray(hipArray, 0, 0, hData, size, hipMemcpyHostToDevice);

    tex.addressMode[0] = hipAddressModeWrap;
    tex.addressMode[1] = hipAddressModeWrap;
    tex.filterMode = hipFilterModePoint;
    tex.normalized = 0;

    hipBindTextureToArray(tex, hipArray, channelDesc);

    float* dData = NULL;
    hipMalloc((void**)&dData, size);

    dim3 dimBlock(16, 16, 1);
    dim3 dimGrid(width / dimBlock.x, height / dimBlock.y, 1);
    hipLaunchKernelGGL(tex2DKernel, dim3(dimGrid), dim3(dimBlock), 0, 0, dData, width, height);
    hipDeviceSynchronize();

    float* hOutputData = (float*)malloc(size);
    memset(hOutputData, 0, size);
    hipMemcpy(hOutputData, dData, size, hipMemcpyDeviceToHost);

    printf("dData: ");
    for (int i = 0; i < 64; i++) {
        printf("%f  ", hOutputData[i]);
    }
    printf("\n");
    for (int i = 0; i < height; i++) {
        for (int j = 0; j < width; j++) {
            if (hData[i * width + j] != hOutputData[i * width + j]) {
                printf("Difference [ %d %d ]:%f ----%f\n", i, j, hData[i * width + j],
                       hOutputData[i * width + j]);
                testResult = false;
                break;
            }
        }
    }
    hipFree(dData);
    hipFreeArray(hipArray);
}
<|endoftext|>


<commit_before>#include <Utils/Logger.h>
#include <Utils/Window.h>
#include <Utils/Windows.h>

#include <GL/glew.h>
#include <GLFW/glfw3.h>

#include <iostream>

namespace Util {

    bool Window::_hintsSet = false;

    Window::Window() : Window(640, 480, "Title") {
        Windows::Get(static_cast<Util::Window*>(nullptr));
    }

    Window::Window(unsigned int width, unsigned int height, const std::string& title) {
        Windows::Get(static_cast<Util::Window*>(nullptr));

        _handle = nullptr;
        _hintsSet = false;
        _isScreenshotFlagSet = false;
        _framesCount = 0;

        setSize(glm::uvec2(width, height));
        setTitle(title);

        setCountingFPS(false);
        setDisplayingFPS(false);
        setDestroyCallback([this]() {
            destroy();
        });
    }

    Window::Window(const glm::uvec2& size, const std::string& title) : Window(size.x, size.y, title) {

    }

    Window::~Window() {
        destroy();
        Windows::unregisterWindow(this);
    }

    Window::operator GLFWwindow*() {
        return getHandle();
    }

    bool Window::create() throw(Util::Exception::FatalError) {
        if(isCreated())
            destroy();

        initializeGLFW();

        if(_hintsSet == false)
            setDefaultHints();

        _handle = glfwCreateWindow(getWidth(), getHeight(), _title.c_str(), nullptr, nullptr);

        Windows::registerWindow(this);

        setFocusCallback();

        setContext();

        initializeGLEW();

        _lastFrame = glfwGetTime();
        _fpsClock.reset();

        if(isCreated())
            Util::Log::LibraryStream().log(
                "Window '" + getTitle() + "' has been created with size: " +
                std::to_string(getSize().x) + "x" + std::to_string(getSize().y)
            );

        return isCreated();
    }

    void Window::update() {
        if(glfwWindowShouldClose(getHandle())) {
            if(_destroyCallback)
                _destroyCallback();

            return;
        }

        if(_isScreenshotFlagSet) {
            getScreenshotNow(_screenshotOrigin, _screenshotSize).save(_screenshotPath);
            _isScreenshotFlagSet = false;
        }

        _thisFrame  = glfwGetTime();
        _frameTime = _thisFrame - _lastFrame;
        _lastFrame  = _thisFrame;

        glfwSwapBuffers(_handle);
        glfwPollEvents();

        if(isCountingFPS()) {
            _framesCount += 1;
            _fpsTime = _fpsClock.getElapsedTime();

            if(_fpsTime > getFPSRefreshRate()) {
                setFPSCount(static_cast<unsigned int>(_framesCount * (1.0 / _fpsTime)));

                if(isDisplayingFPS())
                    appendTitle(std::string(" | FPS: ") + std::to_string(getFPS()));

                if(_fpsCountCallback)
                    _fpsCountCallback(getFPS());

                _framesCount = 0;
                _fpsClock.reset();
            }
        }

        eventAggregator.notifyAll();
    }

    void Window::destroy() {
        if(isCreated()) {
            skipEvents();

            glfwDestroyWindow(_handle);
            _handle = nullptr;

            Util::Log::LibraryStream().log("Window '" + getTitle() + "' has been destroyed");
        }
    }

    void Window::takeScreenshot() {
        std::string fileLocation;
        std::string fileName;

        fileLocation = "";
        fileName = "screenshot.bmp";

        takeScreenshot(fileLocation + fileName);
    }

    void Window::takeScreenshot(const std::string& path) {
        takeScreenshot(path, glm::ivec2(0, 0), getSize());
    }

    void Window::takeScreenshot(const std::string& path, const glm::ivec2& origin, const glm::ivec2& size) {
        _isScreenshotFlagSet = true;
        _screenshotPath = path;
        _screenshotOrigin = origin;
        _screenshotSize = size;
    }

    void Window::registerEvents(Input::Event::Type type) {
        getContext().makeActive(this);

        switch(type) {
            case Input::Event::Type::Key:
                glfwSetKeyCallback(
                    getHandle(),
                    [](GLFWwindow* window, int key, int scancode, int action, int mods) {
                        Util::Input::Key inputKey = static_cast<Util::Input::Key>(key);
                        Util::Input::Action inputAction;
                        Util::Window* inputWindow = Util::Windows::Get(window);

                        if(action == GLFW_PRESS)        inputAction = Util::Input::Action::Press;
                        else if(action == GLFW_REPEAT)  inputAction = Util::Input::Action::Repeat;
                        else if(action == GLFW_RELEASE) inputAction = Util::Input::Action::Release;

                        if(inputWindow) {
                            inputWindow->eventAggregator.registerEvent(
                                new Util::Input::KeyEvent(inputKey, inputAction)
                            );
                        }
                    }
                );
                break;

            case Input::Event::Type::MouseButton:
                glfwSetMouseButtonCallback(
                    getHandle(),
                    [](GLFWwindow* window, int button, int action, int mods) {
                        Util::Input::MouseButton inputButton;
                        Util::Input::Action inputAction;
                        Util::Window* inputWindow = Util::Windows::Get(window);

                        switch(button) {
                            case GLFW_MOUSE_BUTTON_LEFT:   inputButton = Util::Input::MouseButton::Left; break;
                            case GLFW_MOUSE_BUTTON_RIGHT:  inputButton = Util::Input::MouseButton::Right; break;
                            case GLFW_MOUSE_BUTTON_MIDDLE: inputButton = Util::Input::MouseButton::Middle; break;
                        }

                        if(action == GLFW_PRESS)        inputAction = Util::Input::Action::Press;
                        else if(action == GLFW_REPEAT)  inputAction = Util::Input::Action::Repeat;
                        else if(action == GLFW_RELEASE) inputAction = Util::Input::Action::Release;

                        if(inputWindow) {
                            inputWindow->eventAggregator.registerEvent(
                                new Util::Input::MouseButtonEvent(inputButton, inputAction)
                            );
                        }
                    }
                );
                break;

            case Input::Event::Type::MouseMovement:
                glfwSetCursorPosCallback(
                    getHandle(),
                    [](GLFWwindow* window, double x, double y) {
                        Util::Window* inputWindow = Util::Windows::Get(window);

                        if(inputWindow) {
                            inputWindow->eventAggregator.registerEvent(
                                new Util::Input::MouseMovementEvent(
                                    static_cast<float>(x),
                                    static_cast<float>(y)
                                )
                            );
                        }
                    }
                );
                break;

            case Input::Event::Type::MouseScroll:
                glfwSetScrollCallback(
                    getHandle(),
                    [](GLFWwindow* window, double x, double y) {
                        Util::Window* inputWindow;
                        Util::Input::ScrollDirection inputScrollDirection;

                        inputWindow = Util::Windows::Get(window);
                        inputScrollDirection = (y > 0 ? Util::Input::ScrollDirection::Up : Util::Input::ScrollDirection::Down);

                        if(inputWindow) {
                            inputWindow->eventAggregator.registerEvent(
                                new Util::Input::MouseScrollEvent(inputScrollDirection)
                            );
                        }
                    }
                );
                break;
        }
    }

    void Window::registerEvents(std::initializer_list<Input::Event::Type> types) {
        for(auto type : types) {
            registerEvents(type);
        }
    }

    void Window::skipEvents() {
        skipEvents({
            Util::Input::Event::Type::Key,
            Util::Input::Event::Type::MouseButton,
            Util::Input::Event::Type::MouseMovement,
            Util::Input::Event::Type::MouseScroll
        });
    }

    void Window::skipEvents(Input::Event::Type type) {
        switch(type) {
            case Util::Input::Event::Type::Key: glfwSetKeyCallback(getHandle(), nullptr); break;
            case Util::Input::Event::Type::MouseButton: glfwSetMouseButtonCallback(getHandle(), nullptr); break;
            case Util::Input::Event::Type::MouseMovement: glfwSetCursorPosCallback(getHandle(), nullptr); break;
            case Util::Input::Event::Type::MouseScroll: glfwSetScrollCallback(getHandle(), nullptr); break;
        }
    }

    void Window::skipEvents(std::initializer_list<Input::Event::Type> types) {
        for(auto type : types) {
            skipEvents(type);
        }
    }

    void Window::setSize(unsigned int width, unsigned int height) {
        setSize(glm::uvec2(width, height));
    }

    void Window::setSize(const glm::uvec2& size) {
        _windowSize = size;

        if(isCreated())
            glfwSetWindowSize(_handle, getWidth(), getHeight());
    }

    void Window::setPosition(int posX, int posY) {
        setPosition(glm::ivec2(posX, posY));
    }

    void Window::setPosition(const glm::ivec2& position) {
        _windowPosition = position;

        if(isCreated())
            glfwSetWindowPos(getHandle(), getPosition().x, getPosition().y);
    }

    void Window::setTitle(const std::string& title) {
        _title = title;

        if(isCreated())
            glfwSetWindowTitle(_handle, _title.c_str());
    }

    void Window::appendTitle(const std::string& text) {
        std::string appendedTitle = getTitle() + text;

        if(isCreated())
            glfwSetWindowTitle(_handle, appendedTitle.c_str());
    }

    void Window::setDisplayingFPS(bool flag) {
        _isDisplayingFPS = flag;

        if(isDisplayingFPS())
            setCountingFPS(true);
    }

    void Window::setCountingFPS(bool flag) {
        _isCountingFPS = flag;

        setFPSCount(-1);
    }

    void Window::setFPSRefreshRate(double refreshRate) {
        _fpsRefreshRate = refreshRate;
    }

    void Window::setFPSCountCallback(const std::function<void(int)>& function) {
        _fpsCountCallback = function;
    }

    void Window::setDestroyCallback(const std::function<void()>& function) {
        _destroyCallback = function;
    }

    bool Window::isDisplayingFPS() const {
        return _isDisplayingFPS;
    }

    bool Window::isCountingFPS() const {
        return _isCountingFPS;
    }

    double Window::getFPSRefreshRate() const {
        return _fpsRefreshRate;
    }

    int Window::getFPS() const {
        return _fpsCount;
    }

    unsigned int Window::getWidth() const {
        return _windowSize.x;
    }

    unsigned int Window::getHeight() const {
        return _windowSize.y;
    }

    const glm::uvec2& Window::getSize() const {
        return _windowSize;
    }

    const glm::ivec2& Window::getPosition() const {
        return _windowPosition;
    }

    const std::string& Window::getTitle() const {
        return _title;
    }

    bool Window::isCreated() const {
        return (_handle != nullptr);
    }

    bool Window::shouldClose() const {
        return glfwWindowShouldClose(_handle) == GL_TRUE;
    }

    double Window::getFrameTime() const {
        return _frameTime;
    }

    GLFWwindow* Window::getHandle() {
        return _handle;
    }

    GL::Context& Window::getContext() {
        return _context;
    }

    Image Window::getScreenshotNow() {
        return getScreenshotNow(glm::ivec2(0, 0), getSize());
    }

    Image Window::getScreenshotNow(const glm::ivec2& origin, const glm::ivec2& size) {
        Image screenshot;

        unsigned int bits;
        unsigned int rowStride;
        unsigned char* dataPtr;

        bits = 24;
        rowStride = size.x * (bits / 8);
        rowStride = rowStride + (3 - ((rowStride - 1) % 4));
        dataPtr = new unsigned char[rowStride * size.y];

        glReadPixels(origin.x, origin.y, size.x, size.y, GL_RGB, GL_UNSIGNED_BYTE, dataPtr);
        screenshot.load(size.x, size.y, 24, dataPtr);

        delete[] dataPtr;

        return screenshot;
    }

    void Window::initializeGLFW() throw(Util::Exception::FatalError) {
        static bool initialized = false;

        if(initialized == false) {
            // Setting error callback
            static auto errorCallbackFunc = [](int error, const char* description) {
                Util::Log::LibraryStream().logError(std::string("[GLFW] Error ") + std::to_string(error) + std::string(": ") + description);
            };

            glfwSetErrorCallback(errorCallbackFunc);

            // Initializing library
            if(glfwInit() == false) {
                Util::Log::LibraryStream().logError("Failed to initialize GLFW library");
                throw Util::Exception::FatalError(std::string("Failed to initialize GLFW library."));
            }

            initialized = true;
        }
    }

    void Window::initializeGLEW() throw(Util::Exception::FatalError) {
        static bool initialized = false;

        if(initialized == false) {
            glewExperimental = GL_TRUE;

            if(glewInit() != GLEW_OK) {
                Util::Log::LibraryStream().logError("Failed to initialize GLEW library");
                throw Util::Exception::FatalError(std::string("Failed to initialize GLEW library."));
            }

            initialized = true;
        }
    }

    void Window::setHint(int option, int value) {
        glfwWindowHint(option, value);

        _hintsSet = true;
    }

    void Window::setHints(const std::list<std::pair<int, int>>& hints) {
        for(auto& hint : hints)
            glfwWindowHint(hint.first, hint.second);

        _hintsSet = true;
    }

    void Window::setHints(const std::vector<std::pair<int, int>>& hints) {
        for(auto& hint : hints)
            glfwWindowHint(hint.first, hint.second);

        _hintsSet = true;
    }

    void Window::setDefaultHints() {
        glfwWindowHint(GLFW_OPENGL_PROFILE, GLFW_OPENGL_CORE_PROFILE);
        glfwWindowHint(GLFW_CONTEXT_VERSION_MAJOR, 3);
        glfwWindowHint(GLFW_CONTEXT_VERSION_MINOR, 3);
        glfwWindowHint(GLFW_RESIZABLE, GL_FALSE);

        _hintsSet = true;
    }

    void Window::setFPSCount(int fpsCount) {
        _fpsCount = fpsCount;
    }

    void Window::setContext() {
        glfwMakeContextCurrent(getHandle());
        getContext().makeActive(this);
    }

    void Window::setFocusCallback() {
        glfwSetWindowFocusCallback(getHandle(), setFocus);
        setFocus(getHandle(), GL_TRUE);
    }

    void Window::setFocus(GLFWwindow* window, int focused) {
        if(focused == GL_TRUE)
            Windows::setActiveWindow(window);
        else if(focused == GL_FALSE)
            Windows::setActiveWindow(static_cast<GLFWwindow*>(nullptr));
    }

}<commit_msg>[#40] Fixed small bug - windows which objects still existed but `destroy()` method was used on them were not unregistered.<commit_after>#include <Utils/Logger.h>
#include <Utils/Window.h>
#include <Utils/Windows.h>

#include <GL/glew.h>
#include <GLFW/glfw3.h>

#include <iostream>

namespace Util {

    bool Window::_hintsSet = false;

    Window::Window() : Window(640, 480, "Title") {
        Windows::Get(static_cast<Util::Window*>(nullptr));
    }

    Window::Window(unsigned int width, unsigned int height, const std::string& title) {
        Windows::Get(static_cast<Util::Window*>(nullptr));

        _handle = nullptr;
        _hintsSet = false;
        _isScreenshotFlagSet = false;
        _framesCount = 0;

        setSize(glm::uvec2(width, height));
        setTitle(title);

        setCountingFPS(false);
        setDisplayingFPS(false);
        setDestroyCallback([this]() {
            destroy();
        });
    }

    Window::Window(const glm::uvec2& size, const std::string& title) : Window(size.x, size.y, title) {

    }

    Window::~Window() {
        destroy();
    }

    Window::operator GLFWwindow*() {
        return getHandle();
    }

    bool Window::create() throw(Util::Exception::FatalError) {
        if(isCreated())
            destroy();

        initializeGLFW();

        if(_hintsSet == false)
            setDefaultHints();

        _handle = glfwCreateWindow(getWidth(), getHeight(), _title.c_str(), nullptr, nullptr);

        Windows::registerWindow(this);

        setFocusCallback();

        setContext();

        initializeGLEW();

        _lastFrame = glfwGetTime();
        _fpsClock.reset();

        if(isCreated())
            Util::Log::LibraryStream().log(
                "Window '" + getTitle() + "' has been created with size: " +
                std::to_string(getSize().x) + "x" + std::to_string(getSize().y)
            );

        return isCreated();
    }

    void Window::update() {
        if(glfwWindowShouldClose(getHandle())) {
            if(_destroyCallback)
                _destroyCallback();

            return;
        }

        if(_isScreenshotFlagSet) {
            getScreenshotNow(_screenshotOrigin, _screenshotSize).save(_screenshotPath);
            _isScreenshotFlagSet = false;
        }

        _thisFrame  = glfwGetTime();
        _frameTime = _thisFrame - _lastFrame;
        _lastFrame  = _thisFrame;

        glfwSwapBuffers(_handle);
        glfwPollEvents();

        if(isCountingFPS()) {
            _framesCount += 1;
            _fpsTime = _fpsClock.getElapsedTime();

            if(_fpsTime > getFPSRefreshRate()) {
                setFPSCount(static_cast<unsigned int>(_framesCount * (1.0 / _fpsTime)));

                if(isDisplayingFPS())
                    appendTitle(std::string(" | FPS: ") + std::to_string(getFPS()));

                if(_fpsCountCallback)
                    _fpsCountCallback(getFPS());

                _framesCount = 0;
                _fpsClock.reset();
            }
        }

        eventAggregator.notifyAll();
    }

    void Window::destroy() {
        if(isCreated()) {
            skipEvents();

            glfwDestroyWindow(_handle);
            _handle = nullptr;

            Util::Log::LibraryStream().log("Window '" + getTitle() + "' has been destroyed");
            Windows::unregisterWindow(this);
        }
    }

    void Window::takeScreenshot() {
        std::string fileLocation;
        std::string fileName;

        fileLocation = "";
        fileName = "screenshot.bmp";

        takeScreenshot(fileLocation + fileName);
    }

    void Window::takeScreenshot(const std::string& path) {
        takeScreenshot(path, glm::ivec2(0, 0), getSize());
    }

    void Window::takeScreenshot(const std::string& path, const glm::ivec2& origin, const glm::ivec2& size) {
        _isScreenshotFlagSet = true;
        _screenshotPath = path;
        _screenshotOrigin = origin;
        _screenshotSize = size;
    }

    void Window::registerEvents(Input::Event::Type type) {
        getContext().makeActive(this);

        switch(type) {
            case Input::Event::Type::Key:
                glfwSetKeyCallback(
                    getHandle(),
                    [](GLFWwindow* window, int key, int scancode, int action, int mods) {
                        Util::Input::Key inputKey = static_cast<Util::Input::Key>(key);
                        Util::Input::Action inputAction;
                        Util::Window* inputWindow = Util::Windows::Get(window);

                        if(action == GLFW_PRESS)        inputAction = Util::Input::Action::Press;
                        else if(action == GLFW_REPEAT)  inputAction = Util::Input::Action::Repeat;
                        else if(action == GLFW_RELEASE) inputAction = Util::Input::Action::Release;

                        if(inputWindow) {
                            inputWindow->eventAggregator.registerEvent(
                                new Util::Input::KeyEvent(inputKey, inputAction)
                            );
                        }
                    }
                );
                break;

            case Input::Event::Type::MouseButton:
                glfwSetMouseButtonCallback(
                    getHandle(),
                    [](GLFWwindow* window, int button, int action, int mods) {
                        Util::Input::MouseButton inputButton;
                        Util::Input::Action inputAction;
                        Util::Window* inputWindow = Util::Windows::Get(window);

                        switch(button) {
                            case GLFW_MOUSE_BUTTON_LEFT:   inputButton = Util::Input::MouseButton::Left; break;
                            case GLFW_MOUSE_BUTTON_RIGHT:  inputButton = Util::Input::MouseButton::Right; break;
                            case GLFW_MOUSE_BUTTON_MIDDLE: inputButton = Util::Input::MouseButton::Middle; break;
                        }

                        if(action == GLFW_PRESS)        inputAction = Util::Input::Action::Press;
                        else if(action == GLFW_REPEAT)  inputAction = Util::Input::Action::Repeat;
                        else if(action == GLFW_RELEASE) inputAction = Util::Input::Action::Release;

                        if(inputWindow) {
                            inputWindow->eventAggregator.registerEvent(
                                new Util::Input::MouseButtonEvent(inputButton, inputAction)
                            );
                        }
                    }
                );
                break;

            case Input::Event::Type::MouseMovement:
                glfwSetCursorPosCallback(
                    getHandle(),
                    [](GLFWwindow* window, double x, double y) {
                        Util::Window* inputWindow = Util::Windows::Get(window);

                        if(inputWindow) {
                            inputWindow->eventAggregator.registerEvent(
                                new Util::Input::MouseMovementEvent(
                                    static_cast<float>(x),
                                    static_cast<float>(y)
                                )
                            );
                        }
                    }
                );
                break;

            case Input::Event::Type::MouseScroll:
                glfwSetScrollCallback(
                    getHandle(),
                    [](GLFWwindow* window, double x, double y) {
                        Util::Window* inputWindow;
                        Util::Input::ScrollDirection inputScrollDirection;

                        inputWindow = Util::Windows::Get(window);
                        inputScrollDirection = (y > 0 ? Util::Input::ScrollDirection::Up : Util::Input::ScrollDirection::Down);

                        if(inputWindow) {
                            inputWindow->eventAggregator.registerEvent(
                                new Util::Input::MouseScrollEvent(inputScrollDirection)
                            );
                        }
                    }
                );
                break;
        }
    }

    void Window::registerEvents(std::initializer_list<Input::Event::Type> types) {
        for(auto type : types) {
            registerEvents(type);
        }
    }

    void Window::skipEvents() {
        skipEvents({
            Util::Input::Event::Type::Key,
            Util::Input::Event::Type::MouseButton,
            Util::Input::Event::Type::MouseMovement,
            Util::Input::Event::Type::MouseScroll
        });
    }

    void Window::skipEvents(Input::Event::Type type) {
        switch(type) {
            case Util::Input::Event::Type::Key: glfwSetKeyCallback(getHandle(), nullptr); break;
            case Util::Input::Event::Type::MouseButton: glfwSetMouseButtonCallback(getHandle(), nullptr); break;
            case Util::Input::Event::Type::MouseMovement: glfwSetCursorPosCallback(getHandle(), nullptr); break;
            case Util::Input::Event::Type::MouseScroll: glfwSetScrollCallback(getHandle(), nullptr); break;
        }
    }

    void Window::skipEvents(std::initializer_list<Input::Event::Type> types) {
        for(auto type : types) {
            skipEvents(type);
        }
    }

    void Window::setSize(unsigned int width, unsigned int height) {
        setSize(glm::uvec2(width, height));
    }

    void Window::setSize(const glm::uvec2& size) {
        _windowSize = size;

        if(isCreated())
            glfwSetWindowSize(_handle, getWidth(), getHeight());
    }

    void Window::setPosition(int posX, int posY) {
        setPosition(glm::ivec2(posX, posY));
    }

    void Window::setPosition(const glm::ivec2& position) {
        _windowPosition = position;

        if(isCreated())
            glfwSetWindowPos(getHandle(), getPosition().x, getPosition().y);
    }

    void Window::setTitle(const std::string& title) {
        _title = title;

        if(isCreated())
            glfwSetWindowTitle(_handle, _title.c_str());
    }

    void Window::appendTitle(const std::string& text) {
        std::string appendedTitle = getTitle() + text;

        if(isCreated())
            glfwSetWindowTitle(_handle, appendedTitle.c_str());
    }

    void Window::setDisplayingFPS(bool flag) {
        _isDisplayingFPS = flag;

        if(isDisplayingFPS())
            setCountingFPS(true);
    }

    void Window::setCountingFPS(bool flag) {
        _isCountingFPS = flag;

        setFPSCount(-1);
    }

    void Window::setFPSRefreshRate(double refreshRate) {
        _fpsRefreshRate = refreshRate;
    }

    void Window::setFPSCountCallback(const std::function<void(int)>& function) {
        _fpsCountCallback = function;
    }

    void Window::setDestroyCallback(const std::function<void()>& function) {
        _destroyCallback = function;
    }

    bool Window::isDisplayingFPS() const {
        return _isDisplayingFPS;
    }

    bool Window::isCountingFPS() const {
        return _isCountingFPS;
    }

    double Window::getFPSRefreshRate() const {
        return _fpsRefreshRate;
    }

    int Window::getFPS() const {
        return _fpsCount;
    }

    unsigned int Window::getWidth() const {
        return _windowSize.x;
    }

    unsigned int Window::getHeight() const {
        return _windowSize.y;
    }

    const glm::uvec2& Window::getSize() const {
        return _windowSize;
    }

    const glm::ivec2& Window::getPosition() const {
        return _windowPosition;
    }

    const std::string& Window::getTitle() const {
        return _title;
    }

    bool Window::isCreated() const {
        return (_handle != nullptr);
    }

    bool Window::shouldClose() const {
        return glfwWindowShouldClose(_handle) == GL_TRUE;
    }

    double Window::getFrameTime() const {
        return _frameTime;
    }

    GLFWwindow* Window::getHandle() {
        return _handle;
    }

    GL::Context& Window::getContext() {
        return _context;
    }

    Image Window::getScreenshotNow() {
        return getScreenshotNow(glm::ivec2(0, 0), getSize());
    }

    Image Window::getScreenshotNow(const glm::ivec2& origin, const glm::ivec2& size) {
        Image screenshot;

        unsigned int bits;
        unsigned int rowStride;
        unsigned char* dataPtr;

        bits = 24;
        rowStride = size.x * (bits / 8);
        rowStride = rowStride + (3 - ((rowStride - 1) % 4));
        dataPtr = new unsigned char[rowStride * size.y];

        glReadPixels(origin.x, origin.y, size.x, size.y, GL_RGB, GL_UNSIGNED_BYTE, dataPtr);
        screenshot.load(size.x, size.y, 24, dataPtr);

        delete[] dataPtr;

        return screenshot;
    }

    void Window::initializeGLFW() throw(Util::Exception::FatalError) {
        static bool initialized = false;

        if(initialized == false) {
            // Setting error callback
            static auto errorCallbackFunc = [](int error, const char* description) {
                Util::Log::LibraryStream().logError(std::string("[GLFW] Error ") + std::to_string(error) + std::string(": ") + description);
            };

            glfwSetErrorCallback(errorCallbackFunc);

            // Initializing library
            if(glfwInit() == false) {
                Util::Log::LibraryStream().logError("Failed to initialize GLFW library");
                throw Util::Exception::FatalError(std::string("Failed to initialize GLFW library."));
            }

            initialized = true;
        }
    }

    void Window::initializeGLEW() throw(Util::Exception::FatalError) {
        static bool initialized = false;

        if(initialized == false) {
            glewExperimental = GL_TRUE;

            if(glewInit() != GLEW_OK) {
                Util::Log::LibraryStream().logError("Failed to initialize GLEW library");
                throw Util::Exception::FatalError(std::string("Failed to initialize GLEW library."));
            }

            initialized = true;
        }
    }

    void Window::setHint(int option, int value) {
        glfwWindowHint(option, value);

        _hintsSet = true;
    }

    void Window::setHints(const std::list<std::pair<int, int>>& hints) {
        for(auto& hint : hints)
            glfwWindowHint(hint.first, hint.second);

        _hintsSet = true;
    }

    void Window::setHints(const std::vector<std::pair<int, int>>& hints) {
        for(auto& hint : hints)
            glfwWindowHint(hint.first, hint.second);

        _hintsSet = true;
    }

    void Window::setDefaultHints() {
        glfwWindowHint(GLFW_OPENGL_PROFILE, GLFW_OPENGL_CORE_PROFILE);
        glfwWindowHint(GLFW_CONTEXT_VERSION_MAJOR, 3);
        glfwWindowHint(GLFW_CONTEXT_VERSION_MINOR, 3);
        glfwWindowHint(GLFW_RESIZABLE, GL_FALSE);

        _hintsSet = true;
    }

    void Window::setFPSCount(int fpsCount) {
        _fpsCount = fpsCount;
    }

    void Window::setContext() {
        glfwMakeContextCurrent(getHandle());
        getContext().makeActive(this);
    }

    void Window::setFocusCallback() {
        glfwSetWindowFocusCallback(getHandle(), setFocus);
        setFocus(getHandle(), GL_TRUE);
    }

    void Window::setFocus(GLFWwindow* window, int focused) {
        if(focused == GL_TRUE)
            Windows::setActiveWindow(window);
        else if(focused == GL_FALSE)
            Windows::setActiveWindow(static_cast<GLFWwindow*>(nullptr));
    }

}<|endoftext|>


<commit_before>/****************************************************************************

This file is part of the QtMediaHub project on http://www.gitorious.org.

Copyright (c) 2009 Nokia Corporation and/or its subsidiary(-ies).*
All rights reserved.

Contact:  Nokia Corporation (qt-info@nokia.com)**

You may use this file under the terms of the BSD license as follows:

"Redistribution and use in source and binary forms, with or without modification, are permitted provided that the following conditions are met:
* Redistributions of source code must retain the above copyright notice, this list of conditions and the following disclaimer.
* Redistributions in binary form must reproduce the above copyright notice, this list of conditions and the following disclaimer in the documentation and/or other materials provided with the distribution.
* Neither the name of Nokia Corporation and its Subsidiary(-ies) nor the names of its contributors may be used to endorse or promote products derived from this software without specific prior written permission.
THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE."

****************************************************************************/

#include "actionmapper.h"

#include <QKeyEvent>

#include "frontend.h"

#include "qmh-config.h"

ActionMapper::ActionMapper(QObject *p, QString mapPath)
    : QObject(p),
      m_parent(p),
      m_mapPath(mapPath + "/devices/keymaps/")
{
    setObjectName("qmhrpc");

    setupInternalMap();

    m_maps = QDir(m_mapPath).entryList(QDir::Files);
    qDebug() << "Available keyboard maps" << m_maps;

    m_mapName = Config::value("keymap", "stdkeyboard").toString();
    qDebug() << "used keymap" << m_mapName;
    populateMap();
}

void ActionMapper::takeAction(Action action)
{
    if(m_recipient.isNull()) {
        qWarning("Trying to send an action when no recipient is set");
        return;
    }
    QHash<int, Action>::const_iterator it;
    for (it = m_actionMap.constBegin(); it != m_actionMap.constEnd(); ++it) {
        if (it.value() == action)
            break;
    }
    if (it == m_actionMap.constEnd())
        return;
    QKeyEvent keyPress(QEvent::KeyPress, it.key(), Qt::NoModifier);
    qApp->sendEvent(m_recipient.data(), &keyPress);
    QKeyEvent keyRelease(QEvent::KeyRelease, it.key(), Qt::NoModifier);
    qApp->sendEvent(m_recipient.data(), &keyRelease);
}

void ActionMapper::populateMap()
{
    m_actionMap.clear();
    loadMapFromDisk(m_mapPath + m_mapName);
}

bool ActionMapper::loadMapFromDisk(const QString &mapFilePath)
{
    const QMetaObject &ActionMO = ActionMapper::staticMetaObject;
    int enumIndex = ActionMO.indexOfEnumerator("Action");
    QMetaEnum actionEnum = ActionMO.enumerator(enumIndex);

    enumIndex = staticQtMetaObject.indexOfEnumerator("Key");
    QMetaEnum keyEnum = staticQtMetaObject.enumerator(enumIndex);

    QFile mapFile(mapFilePath);
    if (!mapFile.exists() || !mapFile.open(QIODevice::ReadOnly)) {
        qWarning() << "Could not load keymap: " << mapFilePath;
        return false;
    }

    QTextStream mapStream(&mapFile);
    while (!mapStream.atEnd()) {
        QStringList mapping = mapStream.readLine().split("=");
        QStringList keyStrings = mapping.at(1).split(",");
        QList<int> keys;

        int index = actionEnum.keyToValue(mapping[0].toAscii().constData());
        if (index == -1) {
            qWarning() << "\tMapped action is not defined in ActionMapper, skipping: " << mapping[0];
            continue;
        }

        foreach(const QString &key, keyStrings) {
            int keyIndex = keyEnum.keyToValue(QString("Key_").append(key).toAscii().constData());
            if (keyIndex == -1) {
                qWarning() << "\tQt Key does not exist: Key_" << key;
                continue;
            }
            m_actionMap[keyIndex] = static_cast<Action>(index);
        }
    }

    return true;
}

void ActionMapper::setMap(const QString &map)
{
    m_mapName = map;
    populateMap();
}

void ActionMapper::setRecipient(QObject *recipient) {
    recipient->installEventFilter(this);
    QGraphicsView *potentialView = qobject_cast<QGraphicsView*>(recipient);
    if (potentialView) {
        // directly send to the scene, to avoid loops
        m_recipient = QWeakPointer<QObject>(potentialView->scene());
    } else {
        m_recipient = QWeakPointer<QObject>(recipient);
    }
}

bool ActionMapper::eventFilter(QObject *obj, QEvent *event)
{
    static int keyDiscardRate = qMax(1, Config::value("keyDiscardRate", 15));
    static int primitiveKeyCompression = Config::value("keyCompress", true);

    if (event->type() == QEvent::KeyPress || event->type() == QEvent::KeyRelease) {
        QKeyEvent *keyEvent = static_cast<QKeyEvent *>(event);
        int key = keyEvent->key();
        if (m_actionMap.contains(key))
        {
            //squash key events
            if (primitiveKeyCompression
                    && keyEvent->isAutoRepeat())
            {
                if (repeatingKeys.contains(key))
                {
                    repeatingKeys[key] += 1;
                    if (repeatingKeys[key]%keyDiscardRate > 1) {
                        return true;
                    }
                } else {
                    repeatingKeys[key] = 0;
                }
            } else {
                repeatingKeys.remove(key);
            }
            //end squash
            QKeyEvent *e = new QKeyEvent(keyEvent->type()
                        , m_internalActionMap.value(m_actionMap.value(keyEvent->key()))
                        , keyEvent->modifiers()
                        , keyEvent->text()
                        , keyEvent->isAutoRepeat()
                        , keyEvent->count());
            if (!m_recipient.isNull()) {
                QApplication::postEvent(m_recipient.data(), e);
                return true;
            } else {
                qDebug() << "The intended recipient has been forcibly shuffled off this mortal coil";
            }
        }
    }

    // standard event processing
    return QObject::eventFilter(obj, event);
}

void ActionMapper::setupInternalMap()
{
    m_internalActionMap.insert(Left, Qt::Key_Left);
    m_internalActionMap.insert(Right, Qt::Key_Right);
    m_internalActionMap.insert(Up, Qt::Key_Up);
    m_internalActionMap.insert(Down, Qt::Key_Down);
    m_internalActionMap.insert(Enter, Qt::Key_Enter);
    m_internalActionMap.insert(Menu, Qt::Key_Menu);
    m_internalActionMap.insert(Context, Qt::Key_Context1);
    m_internalActionMap.insert(ContextualUp, Qt::Key_PageUp);
    m_internalActionMap.insert(ContextualDown, Qt::Key_PageDown);
    m_internalActionMap.insert(MediaPlayPause, Qt::Key_MediaTogglePlayPause);
    m_internalActionMap.insert(MediaStop, Qt::Key_MediaStop);
    m_internalActionMap.insert(MediaPrevious, Qt::Key_MediaPrevious);
    m_internalActionMap.insert(MediaNext, Qt::Key_MediaNext);
    m_internalActionMap.insert(Back, Qt::Key_Back);
    m_internalActionMap.insert(VolumeUp, Qt::Key_VolumeUp);
    m_internalActionMap.insert(VolumeDown, Qt::Key_VolumeDown);
}

<commit_msg>Fix coding style<commit_after>/****************************************************************************

This file is part of the QtMediaHub project on http://www.gitorious.org.

Copyright (c) 2009 Nokia Corporation and/or its subsidiary(-ies).*
All rights reserved.

Contact:  Nokia Corporation (qt-info@nokia.com)**

You may use this file under the terms of the BSD license as follows:

"Redistribution and use in source and binary forms, with or without modification, are permitted provided that the following conditions are met:
* Redistributions of source code must retain the above copyright notice, this list of conditions and the following disclaimer.
* Redistributions in binary form must reproduce the above copyright notice, this list of conditions and the following disclaimer in the documentation and/or other materials provided with the distribution.
* Neither the name of Nokia Corporation and its Subsidiary(-ies) nor the names of its contributors may be used to endorse or promote products derived from this software without specific prior written permission.
THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE."

****************************************************************************/

#include "actionmapper.h"

#include <QKeyEvent>

#include "frontend.h"

#include "qmh-config.h"

ActionMapper::ActionMapper(QObject *p, QString mapPath)
    : QObject(p),
      m_parent(p),
      m_mapPath(mapPath + "/devices/keymaps/")
{
    setObjectName("qmhrpc");

    setupInternalMap();

    m_maps = QDir(m_mapPath).entryList(QDir::Files);
    qDebug() << "Available keyboard maps" << m_maps;

    m_mapName = Config::value("keymap", "stdkeyboard").toString();
    qDebug() << "used keymap" << m_mapName;
    populateMap();
}

void ActionMapper::takeAction(Action action)
{
    if(m_recipient.isNull()) {
        qWarning("Trying to send an action when no recipient is set");
        return;
    }
    QHash<int, Action>::const_iterator it;
    for (it = m_actionMap.constBegin(); it != m_actionMap.constEnd(); ++it) {
        if (it.value() == action)
            break;
    }
    if (it == m_actionMap.constEnd())
        return;
    QKeyEvent keyPress(QEvent::KeyPress, it.key(), Qt::NoModifier);
    qApp->sendEvent(m_recipient.data(), &keyPress);
    QKeyEvent keyRelease(QEvent::KeyRelease, it.key(), Qt::NoModifier);
    qApp->sendEvent(m_recipient.data(), &keyRelease);
}

void ActionMapper::populateMap()
{
    m_actionMap.clear();
    loadMapFromDisk(m_mapPath + m_mapName);
}

bool ActionMapper::loadMapFromDisk(const QString &mapFilePath)
{
    const QMetaObject &ActionMO = ActionMapper::staticMetaObject;
    int enumIndex = ActionMO.indexOfEnumerator("Action");
    QMetaEnum actionEnum = ActionMO.enumerator(enumIndex);

    enumIndex = staticQtMetaObject.indexOfEnumerator("Key");
    QMetaEnum keyEnum = staticQtMetaObject.enumerator(enumIndex);

    QFile mapFile(mapFilePath);
    if (!mapFile.exists() || !mapFile.open(QIODevice::ReadOnly)) {
        qWarning() << "Could not load keymap: " << mapFilePath;
        return false;
    }

    QTextStream mapStream(&mapFile);
    while (!mapStream.atEnd()) {
        QStringList mapping = mapStream.readLine().split("=");
        QStringList keyStrings = mapping.at(1).split(",");
        QList<int> keys;

        int index = actionEnum.keyToValue(mapping[0].toAscii().constData());
        if (index == -1) {
            qWarning() << "\tMapped action is not defined in ActionMapper, skipping: " << mapping[0];
            continue;
        }

        foreach(const QString &key, keyStrings) {
            int keyIndex = keyEnum.keyToValue(QString("Key_").append(key).toAscii().constData());
            if (keyIndex == -1) {
                qWarning() << "\tQt Key does not exist: Key_" << key;
                continue;
            }
            m_actionMap[keyIndex] = static_cast<Action>(index);
        }
    }

    return true;
}

void ActionMapper::setMap(const QString &map)
{
    m_mapName = map;
    populateMap();
}

void ActionMapper::setRecipient(QObject *recipient)
{
    recipient->installEventFilter(this);
    QGraphicsView *potentialView = qobject_cast<QGraphicsView*>(recipient);
    if (potentialView) {
        // directly send to the scene, to avoid loops
        m_recipient = QWeakPointer<QObject>(potentialView->scene());
    } else {
        m_recipient = QWeakPointer<QObject>(recipient);
    }
}

bool ActionMapper::eventFilter(QObject *obj, QEvent *event)
{
    static int keyDiscardRate = qMax(1, Config::value("keyDiscardRate", 15));
    static int primitiveKeyCompression = Config::value("keyCompress", true);

    if (event->type() == QEvent::KeyPress || event->type() == QEvent::KeyRelease) {
        QKeyEvent *keyEvent = static_cast<QKeyEvent *>(event);
        int key = keyEvent->key();
        if (m_actionMap.contains(key)) {
            //squash key events
            if (primitiveKeyCompression && keyEvent->isAutoRepeat()) {
                if (repeatingKeys.contains(key)) {
                    repeatingKeys[key] += 1;
                    if (repeatingKeys[key]%keyDiscardRate > 1) {
                        return true;
                    }
                } else {
                    repeatingKeys[key] = 0;
                }
            } else {
                repeatingKeys.remove(key);
            }
            //end squash
            QKeyEvent *e = new QKeyEvent(keyEvent->type()
                        , m_internalActionMap.value(m_actionMap.value(keyEvent->key()))
                        , keyEvent->modifiers()
                        , keyEvent->text()
                        , keyEvent->isAutoRepeat()
                        , keyEvent->count());
            if (!m_recipient.isNull()) {
                QApplication::postEvent(m_recipient.data(), e);
                return true;
            } else {
                qDebug() << "The intended recipient has been forcibly shuffled off this mortal coil";
            }
        }
    }

    // standard event processing
    return QObject::eventFilter(obj, event);
}

void ActionMapper::setupInternalMap()
{
    m_internalActionMap.insert(Left, Qt::Key_Left);
    m_internalActionMap.insert(Right, Qt::Key_Right);
    m_internalActionMap.insert(Up, Qt::Key_Up);
    m_internalActionMap.insert(Down, Qt::Key_Down);
    m_internalActionMap.insert(Enter, Qt::Key_Enter);
    m_internalActionMap.insert(Menu, Qt::Key_Menu);
    m_internalActionMap.insert(Context, Qt::Key_Context1);
    m_internalActionMap.insert(ContextualUp, Qt::Key_PageUp);
    m_internalActionMap.insert(ContextualDown, Qt::Key_PageDown);
    m_internalActionMap.insert(MediaPlayPause, Qt::Key_MediaTogglePlayPause);
    m_internalActionMap.insert(MediaStop, Qt::Key_MediaStop);
    m_internalActionMap.insert(MediaPrevious, Qt::Key_MediaPrevious);
    m_internalActionMap.insert(MediaNext, Qt::Key_MediaNext);
    m_internalActionMap.insert(Back, Qt::Key_Back);
    m_internalActionMap.insert(VolumeUp, Qt::Key_VolumeUp);
    m_internalActionMap.insert(VolumeDown, Qt::Key_VolumeDown);
}

<|endoftext|>