Fedora 21 Install (SSD)

Fedora 21 が出た、一年ぶりのメジャー更新で嬉しい。
半年毎に慣れ過ぎて待ちくたびれた。

Fedora

WorkStation というのが今迄どおりのデスクトップのようだ。
とっとと ISO を Brasero で焼いて新規 SSD にインストール。
以前の SSD はそのまま外してバックアップ用、という今迄と同様に。

後は Phenom2 955、AMD 880G というチョッピリ古いマシンのままですが。
普段のメインが iPhone になっちゃってますから壊れるまでこのままでいく。
最新構成の自作 PC より MacBook Air か iPad が欲しいのが本音。
まあそれはどうでもよくて。

今回のインストーラは自動で日本語にはならず自分で選択方式になった。
更に日本語キーボード固定で US キーボードに変更できなかった。
インストール後に変更できるから別に問題は無いですが。

ROOT パスワードがユルくなって 10 文字程度でも「強力」扱いになる。
やっぱり評判が悪かったのだろうね、記号数値を混ぜれば充分だし。

インストール修了で再起動ボタンを押したらフリーズ、いつもの Fedora だ。
電源ボタン長押しから再起動で即イジェクトボタンから DVD-R を取り出す。
うん、インストール自体は成功していたのでよし。

GNOME on Wayland in Fedora 21 | Fedora Magazine

Wayland とノーマルを切り替えしても違いが判らない。
初期 Compiz みたいなヤリスギを期待していたけど超普通だった。

現状 Wayland 状態だとスクリーンショットが一部上手くいかなかった。
Wordpress に画像ドロップアップロードも上手くいかない、まだ実用はキビシイ。
GNOME クラシックは存在意義が解らない、3D のままだし。

Boxes がまた最初から入っている、需要はどうなのか。
Eog がデフォルトビューアに戻っている、何故 20 で除かれたか知らないが。

メニューボタンのアイコンが Firefox, Google Chrome と同じ三本線になった。
GNOME 3.14 Goal: Gear Icons | woGue

icon

このギヤアイコン、つまりメニューボタンの svg 画像だけど。

# Fedora 20
/usr/share/icons/gnome/scalable/emblems/emblem-system-symbolic.svg

# Fedora 21 Gear Icon
/usr/share/icons/Adwaita/scalable/emblems/emblem-system-symbolic.svg

# Fedora 21 Menu Button
/usr/share/icons/Adwaita/scalable/actions/open-menu-symbolic.svg

になっているね、GNOME 3.14 でないとこの svg が無い。
自作アプリで使おうと思ったら 3.14 専用にするか自前にするかしかないようで。
うーん、自作アプリはどうしようか悩む…

あとマウス中ボタンクリックによるペーストが本当に廃止されていた。
このタッチパネルなご時世だから今後はコレでいきましょう。
Middle Button Click to OLE DnD | PaePoi
「昔は良かったオヤジ」予備軍がネット上には凄く多いです。

筆者は特に Gedit の変更は大歓迎、作業スペースは大きいほうがいい。
他 GtkHeaderBar 化やボタン類が異様に大きくなっている。
今後タッチ操作 OS が主になると考えると当然の流れですね。

Nautilus でスクリプトを使うのに右クリックが必要なのも廃止してほしい。
タッチ操作からスクリプトを呼び出す最適手段が思いつかないのが少し悔しい。

そんなことより、初期状態で日本語が入力できなかった。
以前はできたはずなんだがインストーラの仕様変更のせいか?
日本語キーボードの人なら大丈夫なのかな、とにかく変更しなきゃ。
ibus-kkc 自体は入っているようですけど。

ibus_kkc

入力メソッドから[日本語]を削除し[日本語(かな漢字)]を導入。

gsettings set org.gnome.desktop.input-sources sources “[(‘ibus’, ‘kkc’), (‘xkb’, ‘us’)]”

コマンドで ibus-kkc を先頭に入れ替える、GUI で入れ替えできない。
こうしないと再起動毎に切り替えしなきゃいけなくなるので。
US メソッドは実際には残さなくてもいいと思うけど保健として。

ibus-setup にて以下のように。
筆者は直接入力とひらがな切り替えは Alt+Space にした。
ぶっちゃけ直接入力とひらがな以外は使わないよね。

ibus_kkc_setup

これで US キーボードでの日本語入力も問題無し。

google chrome の導入が進化していた。
[プログラムで開く]を選択すると software アプリが立ち上がる。

chrome

まるで最初からストアに登録されていたかのようにインストールできた。
統一感があるって素晴らしいな、OS はこうでなければ。

長くなってきたので続く。

Video playback in GNOME Boxes

GNOME Boxes を一年ぶりくらいで使ってみたけどかなり進化している。
SELinux にまったく引っ掛からなくなっただけでも嬉しい。

終了しても libvirtd プロセスが残り続けていたのも修正しているようだ。
そんなことより

qemu_kvm_video

qemu-kvm 上で動画が再生できるヤン!
仮想マシンもついにココまできたか、高ビットレートは辛いだろうけど。
しかし WebM 動画は Fedora デフォルト状態で再生できるのですね。
我 Y901x も普通に動く。

は、いいのだけど。

前回、今の Boxes は GUI でインストール iso を取り出しできると書いた。
けど再起動する毎にマウントしてしまうようだ、やっぱり XML の編集必須。
下記をを開いて、unknown ってなんだよ…

~/.config/libvirt/qemu/boxes-unknown.xml

comment_out

やはりコメントアウトが必要。
しかし CD-ROM にアクセスできるようにしたいんだけど、どうすれば?
SATA 接続のドライブに CD を入れても認識しないんだが。

https://access.redhat.com/documentation/en-US/Red_Hat_Enterprise_Linux/7/html/Virtualization_Deployment_and_Administration_Guide/sect-Manipulating_the_domain_xml-Devices.html

こんなページを見つけて色々試しているけど駄目。
試しに USB 接続の DVD-ROM を刺してみたら普通に認識した。
手段が解るまでこの手でいくか。

しかしいくら GNOME Boxes を検索しても日本語情報はウチ以外は皆無。
Linux をマジで普段利用している人が少ないから当然かもしれないが。

Gedit 3.14 Plugin

そろそろ新しい Fedora が出るので準備をしなければ。
ベータが出ているようなので試す、面倒だから久々に仮想マシン。

boxes

Boxes(qemu-kvm) はやはり超簡単というか全自動です。
Fedora on Fedora なら 3D デスクトップもストレスが無いのが嬉しい。
細かい指定はできないけどテスト目的には十分すぎる。

ただ Live 中はフル HD なのを認識したのにインストール後は SXGA に。
相変わらずよく解らない認識をする、フル HD 固定だとそれも困るわけですが。
筆者はウインドウモードで使うので 1440×900 に固定。

インストール直後に生 XML から iso を排除する必要はなくなったみたい。
Boxes の設定画面[デバイス]の CD/DVD の所で取り外しできる。

cd_dvd

Alt+Space がウインドウメニューに割り当てされているや。
US キーボードなのでコレで入力切り替えできないと不便なんだよ。
まあ設定で簡単に変えられるのでちゃっちゃと変更。

header_bar

いやぁ、見事に GtkHeaderBar 化されて…
っておい Eye of GNOME さん、あんたが一番メニューバー邪魔でしょ。
これ以上の変更点レビューは正式版の時に。

とにかく Gedit はメニューバーが無いので以前の自作プラグイン達は使えない。

Apps/Gedit/PythonPluginHowTo – GNOME Wiki!
残念ながら 2014.11.16 現在チュートリアルは以前のままだ。

Gedit 3.12 をスルーしたおかげで日本語の先人を見つけた。

うぇーん、GNOME 3.12 にしたら、自家製Linespacing が動かないよー | (まだ無題 ; そのうち変更するかも)

メニュー項目は GMenu 化、GtkApplication 側に登録。
ハンドラは GAction として GtkWindow 側に登録するみたい。
GtkUIManager 関連を消すのを忘れているみたいですけど。

なんか上手くいかないので QuickOpen のソースを参考に少し作り替え。
*.plugin ファイルは以前と同じでいいようです。

#-*- coding:utf-8 -*-

from gi.repository import GObject, Gedit, Gtk, Gio

class TestTestAppActivatable(GObject.Object, Gedit.AppActivatable):
    """
        Set GMenu and Accelerator
    """
    app = GObject.property(type=Gedit.App)

    def __init__(self):
        GObject.Object.__init__(self)

    def do_activate(self):
        # Set Accelerator
        # (key, action name[win.xxxxx], parameter or None)
        self.app.add_accelerator("<Control>B", "win.action_name", None)
        # Append Menu
        self.menu_ext = self.extend_menu("tools-section")
        item = Gio.MenuItem.new("imouto",  "win.action_name")
        self.menu_ext.append_menu_item(item)

    def do_deactivate(self):
        # Remove Accelerator
        self.app.remove_accelerator("win.action_name", None)

class TestTest(GObject.Object, Gedit.WindowActivatable):
    """
        Set GAction
    """
    __gtype_name__ = "TestTest"
    window = GObject.property(type=Gedit.Window)
    def __init__(self):
        GObject.Object.__init__(self)

    def do_activate(self):
        # Set Action
        # (action name, parameter or None)
        action = Gio.SimpleAction.new("action_name", None)
        action.connect('activate', self.on_activate)
        self.window.add_action(action)

    def do_deactivate(self):
        # Remove Action
        self.window.remove_action("action_name")

    def do_update_state(self):
        pass

    def on_activate(self, action, data=None):
        self.messagebox("Yamete Oni-chan")

    def messagebox(self, text):
        dlg = Gtk.MessageDialog(
                self.window,
                Gtk.DialogFlags.MODAL,
                Gtk.MessageType.WARNING,
                Gtk.ButtonsType.OK,
                text)
        r = dlg.run()
        dlg.destroy()

gedit314_plugin

こんな感じで。

とりあえずアクション名を決める。
GtkApplication 側で使う場合は win.xxxxx と接頭子を付ける。
こうしないとメニューがアクティブにならなかった。

次はアクション名にアクセラレータキーに紐付ける
そしてメニューに表示する文字列を決め GMenu を作成。
それをメニューのどこかに突っ込む。
file-section, tools-section, view-section-2 等々。

本体側は先程のアクション名で GAction を作る。
シグナルハンドラをセットし本体に登録、コッチは簡単だね。
後は今迄どおりでいいみたい。

Eye of GNOME プラグインは変更しなくてもいいかな?と思ったけどダメだった。
と思ったら *.plugin の Loader=python3 書き換えだけでイケた。

eog314plugin

Python3 なので unicode 等の処理をお忘れなく。

GTK+ on Ubuntu 14.10

Ubuntu 14.10 が出たので Live を試す。
GTK+ 3.12 のようだが GNOME アプリは全部 3.10 のままだった。

ubuntu1410_gedit

Gedit 3.12 がどうなったか知っているよね。
Apps/Gedit/Screenshots – GNOME Wiki!

Gedit 3.12 向け自作プラグインのテストに使おうと思っていたけど当てが外れた。
Fedora がメインなので 3.12 をすっ飛ばしている状態なのよ。

DistroWatch.com: Ubuntu GNOME
GNOME 版さえ Nautilus 3.10 のまんまカヨ…
Fedora 21 を素直に待つことにする。

それより GMenu と GtkHeaderBar への対応はどうなった?
USB メモリに以下のコードを書いた Python ソースを入れてと。

#!/usr/bin/env python3

import sys
from gi.repository import Gtk, Gio

"""
    GtkHeaderBar on Ubuntu 14.10
    It is enabled.
"""

class Win(Gtk.ApplicationWindow):
    def __init__(self, app):
        Gtk.ApplicationWindow.__init__(self, application=app)
        # Back-Forward Button
        back = Gtk.Button.new_from_icon_name("go-previous-symbolic", Gtk.IconSize.MENU)
        forw = Gtk.Button.new_from_icon_name("go-next-symbolic", Gtk.IconSize.MENU)
        back.set_valign(Gtk.Align.CENTER)
        forw.set_valign(Gtk.Align.CENTER)
        # Back-Forward Containers
        npbox = Gtk.Box.new(Gtk.Orientation.HORIZONTAL, 0)
        Gtk.StyleContext.add_class (npbox.get_style_context(), "linked")
        npbox.pack_start(back, False, False, 0)
        npbox.pack_start(forw, False, False, 0)
        # GtkHeaderBar
        hbar = Gtk.HeaderBar()
        hbar.pack_start(npbox)
        hbar.set_show_close_button(True)
        self.set_titlebar(hbar)
        self.resize(200, 200)
        self.show_all()

class App(Gtk.Application):
    def __init__(self):
        Gtk.Application.__init__(self)

    def do_activate(self):
        self.window.present()

    def do_startup(self):
        Gtk.Application.do_startup(self)
        # AppMenu
        menu = Gio.Menu()
        menu.append("Quit", "app.quit")
        self.set_app_menu(menu)
        # option "quit"
        quit_action = Gio.SimpleAction.new("quit", None)
        quit_action.connect("activate", self.on_quit)
        self.add_action(quit_action)
        self.window = Win(self)
 
    def on_quit(self, action, parameter):
        self.quit()
 
if __name__ == "__main__":
    app = App()
    app.run(sys.argv)

ubuntu1410_hbar

リサイズも移動も可能になっている、密かに対応していたのか。
ただし閉じるボタン位置は左にはならないみたいね。
アプリケーションメニューは Unknown Application Name のまま。

中途半端だなぁ、使えるようになったのは素直に喜ばしいけど。
まだまだ Ubuntu で GTK+ はイケそうに思うけど。

2014年10月17日号 小型ARMデスクトップ“imp”・14.10のFinal Beta・“POODLE”攻撃・OSC Tokyo/Fall・UWN#387:Ubuntu Weekly Topics|gihyo.jp … 技術評論社

次期版 Unity デスクトップは独自 SDK + Qt5 になる。
つまり Android のように Linux ベースだけど専用 API 必須になる???
タッチ無しのデスクトップ環境限定なら Qt アプリは問題なく動くと思うけど。
GTK+ はどうなんだろう?

とはいえ。

updateman

今も相変わらず Python, GTK+ に頼りまくっているようですけど。
本家も 14.04 を勧めているし移行まで中途半端なままだろうね。

GtkHeaderBar の為だけにインストールするのもなぁ。
本当に全然新しくなっていないので Ubuntu 系ブロガーは頭が痛いかも。

document.createElement

さて、カエル王子を引っ張ってピヨ吉を退治する JavaScript だ。
こんな感じにしてみた。

※canvas サイズは 320×400 に固定
※ピヨ吉構造体を用意、HP や X,Y 座標メンバを保持
※ソレを画面に配置する数だけ配列にしておく
※タイマーでカエルが動く毎に for 文で全数チェック
※ピヨ吉にヒットしていれば HP を減らし 0 なら非表示にして通過する
※ピヨ吉すべての HP がゼロになればクリア

とりあえず二回ヒットするとピヨ吉が消える暫定コードに。
カエル王子は 32x32px にしてみたけど iPhone では少し引っ張り辛いかも。

<!DOCTYPE html>
<html>
<head>
<meta charset="utf-8">
<title>ひよこを倒す 01</title>
<!-- for Smart Phone -->
<meta name="viewport" content="
    width=device-width,
    initial-scale=1.0,
    minimum-scale=1.0,
    maximum-scale=1.0,
    user-scalable=no" />
<style>
body {
    margin: 0;
    overflow: hidden;
    -webkit-text-size-adjust: 100%;
}
#ID_CANVAS {
    background-color: #FF7700;
}
</style>
<script type="text/javascript"><!--

    var canvas = null;
    var context = null;
    var ball = null;
    var piyos = [];
    // Constant
    const INIT_X = 160;  // X origin of the image
    const INIT_Y = 280;  // Y origin of the image
    const OFFSET = 16;   // Half of the image size
    const INTERVAL = 20; // n/1000 ms
    const LENGTH = 20;   // Distance the image moves
    const COUNT  = 250;  // INTERVAL*n ms
    // struct
    var piyokichi = function(x, y, hp) {
        this.x = x;
        this.y = y;
        this.hp = hp;
        this.img = null;
    }
    var ballData = function() {
        this.timer_id = -1;
        this.timer_count = 0;
        this.x = 0;
        this.y = 0;
        this.rotation = 0;
    }
    var BallData = new ballData();

    /*
     * Touch Event Handler
    **/
    var onBallTouchStart = function(e) {
        e.preventDefault();
    }
    var onBallTouchMove = function(e) {
        if (BallData.timer_id == -1) {
            context.clearRect(0, 0, canvas.width, canvas.height);
            BallData.x = e.touches[0].pageX;
            BallData.y = e.touches[0].pageY;
            if (BallData.y > 400 - OFFSET)
                BallData.y = 400 - OFFSET;
            context.beginPath();
            context.moveTo(INIT_X, INIT_Y);
            context.lineTo(BallData.x, BallData.y);
            context.stroke();
            moveBall(BallData.x, BallData.y);
        }
    }
    var onBallTouchEnd = function(e) {
        if (BallData.timer_id == -1) {
            BallData.rotation = Math.atan2(BallData.y - INIT_Y, BallData.x - INIT_X)
            BallData.timer_count = COUNT;
            BallData.timer_id = setInterval(onTimer, INTERVAL);
            context.clearRect(0, 0, canvas.width, canvas.height);
        }
    }
    /*
     * Timer Handler
    **/
    var onTimer = function() {
        // Clear ?
        var clear = piyos.length;
        for (var i=0; i<piyos.length; i++) {
            if (piyos[i].hp == 0) clear -= 1;
        }
        if (clear == 0) {
            context.font = "64pt 'Arial'";
            context.fillText("Great!", 10, 100);
            clearInterval(BallData.timer_id);
            BallData.timer_id = -1;
            return;
        }
        if (BallData.timer_count > 0) {
            // Hit the Rival ?
            if (!getRivalHit()) {
                // Hit the Wall ?
                if (BallData.x < OFFSET || BallData.x > canvas.width - OFFSET)
                    BallData.rotation = Math.PI - BallData.rotation;
                if (BallData.y < OFFSET || BallData.y > canvas.height - OFFSET)
                    BallData.rotation = -BallData.rotation;
            }
            // Move Image
            BallData.x -= Math.cos(BallData.rotation) * LENGTH;
            BallData.y -= Math.sin(BallData.rotation) * LENGTH;
            moveBall(BallData.x, BallData.y);
            BallData.timer_count--;
        } else {
            clearInterval(BallData.timer_id);
            BallData.timer_id = -1;
            moveBall(INIT_X, INIT_Y);
        }
    }
    /*
     * Hit Function
    **/
    var getRivalHit = function() {
        for (var i=0; i<piyos.length; i++) {
            if (BallData.x > piyos[i].x - OFFSET &&
                BallData.x < piyos[i].x + OFFSET &&
                BallData.y > piyos[i].y - OFFSET &&
                BallData.y < piyos[i].y + OFFSET) {
                // HP == 0?
                piyos[i].hp -= 5;
                if (piyos[i].hp <= 0) {
                    piyos[i].hp = 0;
                    piyos[i].img.style.display = "none";
                    continue;
                }
                if (BallData.x > piyos[i].x - OFFSET && BallData.x < piyos[i].x + OFFSET)
                    BallData.rotation = Math.PI - BallData.rotation;
                if (BallData.y > piyos[i].y - OFFSET && BallData.y < piyos[i].y + OFFSET)
                    BallData.rotation = -BallData.rotation;
                return true;
            }
        }
        return false;
    }
    /*
     * Move Function
    **/
    var moveBall = function(x, y) {
        ball.style.left = x - OFFSET + "px";
        ball.style.top  = y - OFFSET + "px";
    }
    /*
     * Initialize
    **/
    var init = function() {
        if (window.TouchEvent) {
            canvas = document.getElementById("ID_CANVAS");
            canvas.width = window.innerWidth;
            canvas.height = 400;
            context = canvas.getContext("2d");
            ball = document.getElementById("ID_BALL");
            ball.addEventListener("touchstart",onBallTouchStart);
            ball.addEventListener("touchmove",onBallTouchMove);
            ball.addEventListener("touchend",onBallTouchEnd);
            moveBall(INIT_X, INIT_Y);
            // Back Button
            var back = document.getElementById("ID_BACK");
            back.style.top = canvas.height + "px";
            back.addEventListener("touchend", function() {
                document.location = ".";
            });
            // Create Piyokichi
            piyos.push(new piyokichi(20, 200, 10));
            piyos.push(new piyokichi(50, 30, 10));
            piyos.push(new piyokichi(60, 100, 10));
            piyos.push(new piyokichi(170, 80, 10));
            piyos.push(new piyokichi(280, 120, 10));
            for (var i=0; i<piyos.length; i++) {
                var img = document.createElement("img");
                img.alt = "image";
                img.src = "kaeru01/hiyo02_32x32.gif";
                img.width = 32;
                img.height = 32;
                img.style.position = "absolute";
                img.style.left = piyos[i].x - OFFSET + "px";
                img.style.top  = piyos[i].y - OFFSET + "px";
                document.body.appendChild(img);
                piyos[i].img = img;
            }
        }
    }
    //-->
</script>

</head>
<body onLoad="init()">

<canvas id="ID_CANVAS"></canvas>
<img id="ID_BALL" src="kaeru01/kaeru02_32x32.gif" style="position:absolute" alt="ball">
<img id="ID_BACK" src="back.png" style="position:absolute" alt="back">

</body>
</html>

kaeru01

ひよこを倒す 01

敵の攻撃やターン数、障害物その他についてはまた今度。
長くなってきたので次回から[リンク先で Ctrl+U してね!]にするつもり。

他に今回やってみたこと。

canvas に文字列を表示するには fillText
[MS Pゴシック]なんてこのスマートフォン時代に指定しないで下さい。

context.font = "64pt 'Arial'";
context.fillText("Great!", 10, 100);

img タグを動的に作るには createElement
その img を非表示にするには img.style.display = “none”;

var img = document.createElement("img");
document.body.appendChild(img);

後は前回までのコードを少し応用しただけでココまで作れた。
しかしヒット判定は四方チェックしてから振り分けしか手段が無いのかな?
ネットに転がっているブロック崩しのコードを色々見るもイマイチ参考にならないし。
全部グローバル変数で読み辛い人多過ぎだし、構造体やクラスって凄く便利だよ。

今回は[フリー素材 動物アイコン]で適当に検索して以下をお借りしました。
1キロバイトの素材屋さん-無料素材の配布/可愛いアイコン・動く顔文字などのフリー素材集-

カエルとひよこがあって丁度よかった、32x32px に変更しただけ。
本格的に作る時があったらオリジナルキャラにしますが筆者は絵心が…