Friday, May 15, 2026

Android java: calculation for ime wreda keyboard build 2026.09

Code


    // Emoji column and row
    int emojiGridColumns = 8; // store number of emoji
    float emojiGridRows = 3.5f; // store row in emoji
    // IME View size
    int finalWidth=0,finalHeight=0; // final value for IME View
    
    // -------------- set ime view size and emoji -----------------------
    // old version
    private void setIMEViewSizeAndEmojiOld() {
        // 1. Get the Calculator instance
        WindowMetricsCalculator calculator = WindowMetricsCalculator.getOrCreate();
        // 2. Compute current metrics for this specific Activity
        // This works on API 24 (Split Screen) up to API 37
        WindowMetrics metrics = calculator.computeCurrentWindowMetrics(myWredaKeyboard);

        // 3. Get the bounds (Rect)
        Rect bounds = metrics.getBounds();
        float density = myWredaKeyboard.getResources().getDisplayMetrics().density;

        int screenWidth = bounds.width();
        int screenHeight = bounds.height();
        boolean isWide = screenWidth > screenHeight;
        // Handle Navigation Bar Overlap (API 24+ Compatibility)
        // MANUAL INSET
        if (isWide) {
            // In landscape, navigation bars are usually on the left or right.
            // 48dp is the standard minimum size for system bars.
            int navBarWidth = (int) (48 * density);

            // Subtract space for both sides to be safe and centered
            screenWidth = screenWidth - (2 * navBarWidth);
        }

        float screenRatio = (float) screenWidth/screenHeight;
        float smallestWidthDp = Math.min(screenWidth, screenHeight) / density;

        int numberOfKeysColumn = 10;
        int numberOfKeysRow = 5;
        float keyWHRatioPortrait = 0.5f;// width : height = 1:2


        // --- ADAPTIVE ENGINE ---

        if (screenRatio > 0.85f && screenRatio < 1.2f) {
            // 📱 FOLDABLES / SQUARE DEVICES (Unfolded state)

            // 1. Keep it short. 25% is good because the screen is huge vertically.
            finalHeight = (int) (0.25f * screenHeight);

            // 2. Calculate the "Perfect Square" key size
            // If keys are square, width = height.
            int keyHeight = finalHeight / numberOfKeysRow;

            // 3. Set Width based on the Square Key
            // We multiply keyHeight by columns to get a keyboard that fits the keys perfectly.
            int idealWidth = keyHeight * numberOfKeysColumn;

            // 4. Center it
            // This ensures the keyboard doesn't stretch. It will sit in the middle
            // with empty space on the sides, making it reachable for thumbs.
            finalWidth = Math.min(screenWidth, idealWidth);

            // Debug for Foldable
            //Log.e("dedetok", "Foldable Mode active. Width constrained to: " + finalWidth); // debug

        } else if (isWide) {

            // 📺 LANDSCAPE (TV, Tablet, Wide Phone)
            // Goal: "Fat" Keys (Wide). You mentioned "landscape make it fat"
            // To make them fat (wider than tall), we DIVIDE by the 0.5 ratio

            if (smallestWidthDp >= 600) {
                // ️ TABLET LANDSCAPE: Keep it shorter so it doesn't cover the whole screen
                finalHeight = (int) (0.45f * screenHeight);
            } else {
                //  PHONE LANDSCAPE: Make it "bigger" to be usable
                finalHeight = (int) (0.55f * screenHeight);
            }
            // Re-calculate keyHeight AFTER setting finalHeight
            int keyHeight = finalHeight / numberOfKeysRow;
            int idealWidth = (int) (keyHeight / keyWHRatioPortrait * numberOfKeysColumn);
            //Log.e("dedetok", "screenWidth "+screenWidth+" idealWidth "+idealWidth);// debug

            // Use min to ensure it doesn't bleed off screen
            finalWidth = Math.min(screenWidth, idealWidth);

        } else {
            // phone
            if (smallestWidthDp >= 600) {
                // 🏗️ TABLET LANDSCAPE: Keep it shorter so it doesn't cover the whole screen
                finalHeight = (int) (0.30f * screenHeight);
                int keyHeight = finalHeight / numberOfKeysRow;
                int idealWidth = (int) (keyHeight / keyWHRatioPortrait * numberOfKeysColumn);

                // Use min to ensure it doesn't bleed off screen
                finalWidth = Math.min(screenWidth, idealWidth);
            } else {
                // 📱 PHONE PORTRAIT: Make it "bigger" to be usable
                finalHeight = (int) (0.35f * screenHeight);
                finalWidth = screenWidth;
            }

        }
        //Log.e("dedetok", "Width: "+finalWidth+" Height: "+finalHeight); // debug

        // ------------ now calculate emoji grid column and row
        int availableHeight = (int)(finalHeight * 0.8f);
        int emojiSize;
        if (screenRatio > 0.85f && screenRatio < 1.2f) {
            // Treat foldables like portrait tablets
            int targetRows = 4;
            int emojiSizeBox = (availableHeight / targetRows) + 6;
            emojiSize = Math.max(emojiSizeBox, 120); // slightly bigger for the big screen

            emojiGridColumns = finalWidth / emojiSize;
            emojiGridRows = (float) availableHeight / emojiSize;
        } else if (isWide && smallestWidthDp < 600) {
            // Force 9 columns to make emojis large enough to only fit ~2 rows
            emojiGridColumns = 9;
            emojiSize = finalWidth / emojiGridColumns;
            emojiGridRows = (float) availableHeight / emojiSize;
        } else {
            // Portrait: Standard 4 rows
            int targetRows = 4;
            int emojiSizeBox = (availableHeight / targetRows) + 6; // 6 space
            emojiSize = Math.max(emojiSizeBox, 100);

            emojiGridColumns = finalWidth / emojiSize;
            emojiGridRows = (float) availableHeight / emojiSize;
        }
    }    

Build 2026.09 

Friday, May 1, 2026

lamp debian 13: configure codeigniter 4


Minimum codeigniter 4.7.2: php 8.2

Target access http://localhost/app1 

Download zip codeiginiter 4 from official site and extract into folder root e.g. /home/[username]/ci4/app1.

Install required php php-mbstring

# apt install php-intl php-mbstring
# systemctl restart apache2

The following PHP extensions should be enabled on your server:

  • php-curl
  • php-json
  • php-mysqlnd/php-mysql
  • php-imagick php-gd
  • php-xml/php-simplexml

Default root folder

+-- app
+-- public
+-- tests
+-- spark
+-- system
+-- writable
|
+composer.json
+env
+LICENSE
+preload.php
+phpunit.xml.dist
+README.md

Change group and permission:


# usermod -a -G www-data [username]
# groups [username]
[username] : [username] cdrom floppy audio dip www-data video plugdev users netdev bluetooth lpadmin scanner libvirt
# chgrp www-data /home/[username] /home/[username]/ci4 /home/[username]/ci4/app1
# chmod g+x /home/[username] /home/[username]/ci4 /home/[username]/ci4/app1 

Edit /home/[username]/ci4/app1/app/Config/


<?php

namespace Config;

use CodeIgniter\Config\BaseConfig;

class App extends BaseConfig
{
    /**
     * --------------------------------------------------------------------------
     * Base Site URL
     * --------------------------------------------------------------------------
     *
     * URL to your CodeIgniter root. Typically, this will be your base URL,
     * WITH a trailing slash:
     *
     * E.g., http://example.com/
     */
    //public string $baseURL = 'http://localhost:8080/';
    public string $baseURL = 'http://localhost/app1/';


Option 1 Using subpath in user home folder

assume your root codeigniter is /home/[username]/ci4/app1

edit file /etc/apache2/sites-enabled/000-default.conf and restart


    <virtualhost>
	# The ServerName directive sets the request scheme, hostname and port that
	# the server uses to identify itself. This is used when creating
	# redirection URLs. In the context of virtual hosts, the ServerName
	# specifies what hostname must appear in the request's Host: header to
	# match this virtual host. For the default virtual host (this file) this
	# value is not decisive as it is used as a last resort host regardless.
	# However, you must set it for any further virtual host explicitly.
	#ServerName www.example.com

	ServerAdmin webmaster@localhost
	DocumentRoot /var/www/html

        # --- SUBPATH
        Alias /app1 /home/[username]/ci4/app1/public
        <directory app1="" ci4="" home="" public="" username="">
           Options Indexes FoolowSymLinks
           AllowOverride All
           Require all granted
        </directory>

~# apache2ctl configtest
AH00558: apache2: Could not reliably determine the server's fully qualified domain name, using 127.0.1.1. Set the 'ServerName' directive globally to suppress this message
Syntax OK
~# systemctl restart apache2

No configuration in this option.

Option 2 Using subpath in copy public folder to /var/www/html/ 

this is close to shared web hosting

create folder app1 inside /var/www/html and move all content inside [ci4_project_root]/public  into app1

Edit file index.php


/*
 *---------------------------------------------------------------
 * BOOTSTRAP THE APPLICATION
 *---------------------------------------------------------------
 * This process sets up the path constants, loads and registers
 * our autoloader, along with Composer's, loads our constants
 * and fires up an environment-specific bootstrapping.
 */

// LOAD OUR PATHS CONFIG FILE
// This is the line that might need to be changed, depending on your folder structure.
//require FCPATH . '../app/Config/Paths.php'; // NOT USED
// ^^^ Change this line if you move your application folder 
// USE ABOSOLUTE PATH
require '/home/[username]/ci4/app1/app/Config/Paths.php'; 

You may do this in web shared hosting. the deference is /var/www/html and /home/[username]/public_html (usually in cpanel).

NOTE: choose one of the options above, don't mix it.

Using Sub domain e.g. app1.example.com (not tested)

Subdomain Method (Best Practice)

This is the cleaner and more secure method as it keeps the entire framework structure intact.

Steps:

  1. Upload and extract your CodeIgniter zip into the folder you specified above e.g. /home/[username]/ci4/app1/.
  2. In cPanel/Plesk, create a Subdomain (e.g., app1.domain.com).
  3. Set its Document Root for sub domain to the public folder of your project (e.g., /home/[username]/ci4/app1/public) .
  4. No code changes are needed. Your setup is complete.

For development, you can find file name env. Edit it, set CI_ENVIRONMENT = development (default is production), save it as .env (with . in leading file name).

 

Debian 13: configure php apache environment for personal development

Add user to group of www-data (this is example for CodeIgniter 4 Framework)

# usermod -a -G www-data [username]
# groups [username]
[username] : [username] cdrom floppy audio dip www-data video plugdev users netdev bluetooth lpadmin scanner libvirt
# chgrp www-data /home/[username] /home/[username]/ci4 /home/[username]/ci4/app1
# chmod g+x /home/[username] /home/[username]/ci4 /home/[username]/ci4/app1

Folder structure for code igniter api

/home/[username]/ci4/app1
|
+-- app
+-- public
+-- tests
+-- spark
+-- system
+-- writable
|
+composer.json
+env
+LICENSE
+preload.php
+phpunit.xml.dist
+README.md    

Assume apache already installed, edit file /etc/apache2/sites-enabled/000-default.conf and add virtual folder e.g localhost/app1


    <virtualhost>
	# The ServerName directive sets the request scheme, hostname and port that
	# the server uses to identify itself. This is used when creating
	# redirection URLs. In the context of virtual hosts, the ServerName
	# specifies what hostname must appear in the request's Host: header to
	# match this virtual host. For the default virtual host (this file) this
	# value is not decisive as it is used as a last resort host regardless.
	# However, you must set it for any further virtual host explicitly.
	#ServerName www.example.com

	ServerAdmin webmaster@localhost
	DocumentRoot /var/www/html

        # --- SUBPATH
        Alias /app1 /home/[username]/ci4/app1/public
        <directory app1="" ci4="" home="" public="" username="">
           Options Indexes FoolowSymLinks
           AllowOverride All
           Require all granted
        </directory>

~# apache2ctl configtest
AH00558: apache2: Could not reliably determine the server's fully qualified domain name, using 127.0.1.1. Set the 'ServerName' directive globally to suppress this message
Syntax OK

Replace [username] with yours

Restart apache


Monday, April 6, 2026

Debian 13: trouble shooting Android Debug Bridge (adb) on kernel 6.12.74

After i upgrade the kernel from 6.12.67 to kernel 6.12.74, the kernel can not detect my phone to test android application.

Do this using command

# modprobe cdc-acm
# modprobe usb-storage
# modprobe usbserial
# usermod -aG plugdev [username]
$ groups [username]
[username] : [username] cdrom floppy audio dip video plugdev users netdev bluetooth lpadmin scanner libvirt

make sure [username] in group of plugdev


Thursday, March 12, 2026

Debian 13: installing google chrome

google chrome system requirements for debian

  • Release: Debian 10+
  • Processor: Intel Pentium 4 or later that is SSE3 capable 64-bit
  • RAM: 2GB is a minimum in some contexts, 4GB or more is recommended.
  • Storage: At least 16GB, though 32GB or more is recommended for optimal performance. 

 Download key and configure apt sources  

~# wget -q -O - https://dl.google.com/linux/linux_signing_key.pub | sudo tee /etc/apt/trusted.gpg.d/google.asc >/dev/null
~# ls /etc/apt/trusted.gpg.d/ | grep google
google.asc
google-chrome.gpg
~# curl -fsSL https://dl.google.com/linux/linux_signing_key.pub | sudo gpg --dearmor -o /usr/share/keyrings/google-chrome.gpg
~# echo "deb [arch=amd64 signed-by=/usr/share/keyrings/google-chrome.gpg] http://dl.google.com/linux/chrome/deb/ stable main" | sudo tee /etc/apt/sources.list.d/google-chrome.list > /dev/null

Update repository

~# apt update
Hit:1 http://deb.debian.org/debian trixie-backports InRelease
Hit:2 https://deb.debian.org/debian trixie InRelease   
Hit:3 https://deb.debian.org/debian trixie-updates InRelease
Hit:4 https://dl.google.com/linux/chrome/deb stable InRelease       
Hit:5 https://security.debian.org/debian-security trixie-security InRelease
Hit:6 http://httpredir.debian.org/debian trixie InRelease
All packages are up to date
~# ls /etc/apt/sources.list.d/
google-chrome.list

Installing google chrome stable

~# apt install  google-chrome-stable 
Installing:                     
  google-chrome-stable

Summary:
  Upgrading: 0, Installing: 1, Removing: 0, Not Upgrading: 0
  Download size: 127 MB
  Space needed: 413 MB / 18.9 GB available

Get:1 https://dl.google.com/linux/chrome/deb stable/main amd64 google-chrome-stable amd64 146.0.7680.71-1 [127 MB]
Fetched 127 MB in 57s (2,254 kB/s)                                             
Selecting previously unselected package google-chrome-stable.
(Reading database ... 189434 files and directories currently installed.)
Preparing to unpack .../google-chrome-stable_146.0.7680.71-1_amd64.deb ...
Unpacking google-chrome-stable (146.0.7680.71-1) ...
Setting up google-chrome-stable (146.0.7680.71-1) ...
update-alternatives: using /usr/bin/google-chrome-stable to provide /usr/bin/x-w
ww-browser (x-www-browser) in auto mode
update-alternatives: using /usr/bin/google-chrome-stable to provide /usr/bin/gno
me-www-browser (gnome-www-browser) in auto mode
update-alternatives: using /usr/bin/google-chrome-stable to provide /usr/bin/goo
gle-chrome (google-chrome) in auto mode
Processing triggers for man-db (2.13.1-1) ...
Processing triggers for desktop-file-utils (0.28-1) ...

Done....