بسم لله الرحمن الرحيم
الحمدلله رب العالمين و الصلاة و السلام على سيد المرسلين، سيدنا محمد وعليه أفضل الصلاة و أتم التسليم ثم أما بعد …
تمهيد
لا يخفى على الجميع برنامج محرر النصوص emacs والذي يمكن بناؤه ليعمل على الطرفية فقط أو على x11 أو على gtk، فمثلا emacs-lucid التي تعمل على X11 الموجود في دبيان وفي فويد لينكس emacs-x11، كما أننا لو سألنا أحدهم كيف يمكنك بناء مدير نوافذ مثل i3 أو Suckless DWM أو معرض الصور في sxiv أو برنامج mupdf و غيرها من التطبيقات؟ هل هي Qt أم أنها GTK ؟ لا ، هل هي wayland؟ لا، اذًا ما هي ؟
يعتقد البعض بأن الواجهات تُبنى فقط من خلال Qt أو من خلال GTK لان أغلب المصادر والكتب تتحدث عنهما ولكن السؤال هل لأن أغلب المصادر و الكتب تتحدث عنهما يعني أنهما كل شيء؟ بالطبع لا، في هذا الموضوع سوف أقوم ببناء نافذة مكتوب عليها “Welcome To Aosus” بلغة برمجة سي مع شرح الدوال المستخدمة فيها والتي بدورها سنفهم كيف يمكن بناء مدير نوافذ أو برامج عن طريق تصميم الواجهات بـمكتبات X11
ماذا سنحتاج ؟
من المتوقع أنك تعمل على Xorg لان ما يتم التعامل معه هنا قد لا يعمل في Wayland أو الأماكن الأخرى.
1- تحميل المكتبة Xlib
فبعد تثبيت Xorg يجب تحميل المكتبة X11:
في ديبيان
sudo apt install libx11-dev
في أرش لينكس
sudo pacman -S libx11
في فويد لينكس
sudo xbps-install libX11-devel
على FreeBSD
doas pkg install libX11
في OpenBSD و جنتو لن تحتاج إلى تثبيت المكتبة لانها مضمنة مع حزمة Xorg
2- سنحتاج إلى مترجم للغة c
سوف نستخدم مترجم جنو gcc ولكن الطريقة يمكن تشغيلها على cc والتي هي مضمنة ضمن أنظمة تشغيل يونكس (معظمها)، ولتحميل مترجم جنو :
في ديبيان
sudo apt install build-essential
في أرش لينكس
sudo pacman -S base-devel
في فويد لينكس
sudo xbps-install base-devel
اذا لم تتمكن من تحميل أدوات جنو يمكن أن تكمل باستعمال cc ، هذه الخطوة كانت مهمة للمهاجرين الجدد
3- محرر نصوص
أي محرر نصوص سيفي بالغرض.
لنكتب البرنامج
سنشرح أولا الدوال ثم سنجمع أجزاء البرنامج في ملف واحد في كل خطوة سأشرح ماذا تعني
1- تضمين المكتبات ( Preprocessor) المعالجة المسبقة
لا يخلو أي برنامج C من تضمين المكتبات و نحن هنا في هذا البرنامج نحتاج إلى ثلاث مكتبات
#include<stdio.h>
#include<stdlib.h>
#include<X11/Xlib.h>
الشرح:
- include<stdio.h> تتضمن مكتبات معيارية للعرض والكتابة
- include<stdlib.h> تتضمن مكتبات النظام مثل الخروج exit()
- include<X11/Xlib.h> تتضمن مكتبات X11
2- انشاء الدالة الرئيسة
كل برنامج C يمتلك دالة main لذا سنكتب
int main(void)
{
return 0;
}
الشرح:
لا يخلو برنامج سي من الدالة main() وأدخلنا void كمعالمات للدالة لأننا لا نريد استقبل اي مدخلات أثناء استدعائها من الطرفية.
3- عرض الجلسة
هنا سوف نقوم بأهم أمر في مكتبة Xlib وهو الأمر الذي سيقوم بتشغيل البرنامج حيث يقوم بالإتصال مع خادم X11
Display *display = XOpenDisplay(NULL);
if(display == NULL){
fprintf(stderr, "ERROR: you couldn't open!!\n");
exit(1);
}
XCloseDisplay(display);
الشرح:
نوع البينات Display يجب أن تحتوي على طرفين مهمين
الطرف Display *display = XOpenDisplay(NULL); الذي سيقوم بقابلية فتح النافذة.
و الطرف XCloseDisplay(display); سيقوم بإغلاق البرنامج.
أي سيعمل البرنامج في جلسة ثم يغلق ولكن فيما بينهما سيكون البرنامج فمثلاً الجزء :
if(display == NULL){
fprintf(stderr, "ERROR: you couldn't open!!\n");
exit(1);
}
يفيد أن اذا كان هناك خلل في الجلسة (الإتصال بخادم X11) سوف يقوم بارسال رسالة ERROR: you couldn't open!! ولن يعمل.
4- شكل النافذة
لعرض النافذة يجب تحديد ألوانها و أطوالها لذلك سنستخدم الدالة XCreateSimpleWindow()
Window window = XCreateSimpleWindow(
display,
XDefaultRootWindow(display),
0, 0,
800,
600,
1,
2,
0x00FFFFFF);
الشرح :
إن المعلمات تفيد معلومات عن النافذة فهي كالتالي
- display اسم الإتصال الذي إتصلنا به للخادم
- XDefaultRootWindow(display) تفيد أنها الشاشة الرئيسة للبرنامج
- 0 , 0 حدود الزوايا
- 800 و 600 الطول و العرض
- 1 هو للإطار و تحديد البيكسيلات بها
- 2 حجم سمك الإطار
- 0x00FFFFFF لون الخلفية أبيض
معلومة مهمة / لون الخلفية يحدد من 0 إلى 255 كما في بعض المصادر ولكن يمكنا استخدام كود الألوان بإستخدام بالنظام الست عشري بوضع صفرين قبل الرمز 0x00.
4- عنوان النافذة
إذا أردت إنشاء عنوان للنافذة
XStoreName(display, window, "Welcome Window Test");
5- انشاء سياق الرسوم
GC gc = XCreateGC(display, window, 0, NULL);
XFreeGC(display, gc);
الشرح:
تنشئ دالة XCreateGC() سياقًا للرسومات وتعيد GC. يمكن استخدام GC مع أي عنصر قابل للرسم له نفس الجذر والعمق مثل العنصر القابل للرسم المحدد. ولكن تقوم دالة XFreeGC() بتدمير GC المحدد بالإضافة إلى كل مساحة التخزين المرتبطة به.
6- عرض الأخطاء إن وجدت في المتغير GC
XSetForeground(display, gc, BlackPixel(display, DefaultScreen(display)));
7- التفاعل مع البرنامج
في مشروعنا الحالي سنقوم بالتفاعل مع المستخدم و نريد طباعة العبارات على النافذة:
XSelectInput(display, window,ExposureMask | KeyPressMask);
ا
8- اظهر النافذة
النافذة لن تظهر إلا بتحديدها بالخريطة و تدعى هذه الطريقة بالـ Mapping
XMapWindow(display, window);
XSync(display, False);
9- حلقة التشغيل
int quit = 0;
while(!quit){
XEvent event = {0};
XNextEvent(display, &event);
XDrawString(display, window, gc, 20, 50, "Welcome To Aosus" , 17);
if(event.type) {
switch(event.type) {
case KeyPress: {
printf("Thanks for using this app\n");
quit = 1;
}
}
}
}
الشرح:
سوف نقوم بتدوير الحلقات لتشغيل البرنامج من خلال الدالة while() ثم سنطبع Welcome To Aosus من خلال الدالة XDrawString ثم سنستقبل أي زر من سيضغطه المستخدم لغلق البرنامج.
أخيراً في هذه النقطة سوف نجمع أجزاء المشروحة في ملف مصدري واحد كالتالي ولنسمي الملف aosus.c:
#include<stdio.h>
#include <X11/keysym.h>
#include<stdlib.h>
#include<X11/Xlib.h>
int main(void)
{
Display *display = XOpenDisplay(NULL);
if(display == NULL){
fprintf(stderr, "ERROR: you couldn't open!!\n");
exit(1);
}
Window window = XCreateSimpleWindow(
display,
XDefaultRootWindow(display),
0, 0,
800,
600,
1,
2,
0x00FFFFFF);
XStoreName(display, window, "Welcome Window Test");
GC gc = XCreateGC(display, window, 0, NULL);
XSetForeground(display, gc, BlackPixel(display, DefaultScreen(display)));
XSelectInput(display, window,ExposureMask | KeyPressMask);
XMapWindow(display, window);
XSync(display, False);
int quit = 0;
while(!quit){
XEvent event = {0};
XNextEvent(display, &event);
XDrawString(display, window, gc, 20, 50, "Welcome To Aosus" , 17);
if(event.type) {
switch(event.type) {
case KeyPress: {
printf("Thanks for using this app\n");
quit = 1;
}
}
}
}
XFreeGC(display, gc);
XCloseDisplay(display);
return 0;
}
الآن نترجم بربطه مع X11 بتفعيل الخيار -lX11
gcc aosus.c -o test -lX11
ينطبق نفس الأمر مع cc
cc aosus.c -o test -lX11
نفذ الأمر :
./test
المخرجات :
ختاماً
من هنا يمكن صنع مدير النوافذ و برامجك باستخدام Xlib ولكن هذا لا يعني أنك لن تحتاج إلى مكتبات الأخرى مثل Xcb و مكتبة Xinerama و غيرها من المكتبات، دائما ما أشير إلى هذه المكتبات كونها تشرح مكونات النظام وتعطينا معلومات حول الواجهات أكثر من غيرها، اذا كنت مهتم للـ Xlib فهناك كتاب يشرح كل هذه التفاصيل بالاضافة إلى الموقع لشخص كتب معظم الدوال في موقعه و أعلم أنني تجاوزت عن بعض النقاط لكي لا الموضوع أكثر، أعتذر لطول الموضوع و أرجو من الله أن يوفقنا وإياكم لكل ما يحبه و يرضاه.
